Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Broken code?

Broken code?

Scheduled Pinned Locked Moved C / C++ / MFC
questiondebugginghelptutorial
14 Posts 5 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T Offline
    T Offline
    Tydia kun
    wrote on last edited by
    #1

    This really bothers me. See, I have a class and two variables of the same class, CBuffer, named Buffer and RetBuf. So, there's a line of code that says Buffer = RetBuf (class CBuffer has an overloaded operator = that takes another CBuffer& as argument). So even in debug, the compiler generates the following code: 004B1E48 mov eax,dword ptr [ebp+18h] 004B1E4B mov dword ptr [ebp+10h],eax 004B1E4E mov ecx,dword ptr [ebp+1Ch] 004B1E51 mov dword ptr [ebp+14h],ecx WHICH IS COMPLETELY WRONG! Does anyone know why this may happen and how to fix such a thing? I already tried a rebuild without success. All we long-time developers should know that unless there's an overload that takes a CBuffer& as argument, this operation is impossible. But there is one such overload, though, although the compiler does not generate code to call it, but instead perform pointer assigns! It's like it's thinking they're pointers, and therefore trying to assign the RetBuf pointer to the Buffer pointer, which again is not possible since there's no cast and they're different types! This boggles my mind! What IS the compiler doing?!

    S M 2 Replies Last reply
    0
    • T Tydia kun

      This really bothers me. See, I have a class and two variables of the same class, CBuffer, named Buffer and RetBuf. So, there's a line of code that says Buffer = RetBuf (class CBuffer has an overloaded operator = that takes another CBuffer& as argument). So even in debug, the compiler generates the following code: 004B1E48 mov eax,dword ptr [ebp+18h] 004B1E4B mov dword ptr [ebp+10h],eax 004B1E4E mov ecx,dword ptr [ebp+1Ch] 004B1E51 mov dword ptr [ebp+14h],ecx WHICH IS COMPLETELY WRONG! Does anyone know why this may happen and how to fix such a thing? I already tried a rebuild without success. All we long-time developers should know that unless there's an overload that takes a CBuffer& as argument, this operation is impossible. But there is one such overload, though, although the compiler does not generate code to call it, but instead perform pointer assigns! It's like it's thinking they're pointers, and therefore trying to assign the RetBuf pointer to the Buffer pointer, which again is not possible since there's no cast and they're different types! This boggles my mind! What IS the compiler doing?!

      S Offline
      S Offline
      Stephen Hewitt
      wrote on last edited by
      #2

      Where's code code for CBuffer? A snippit of a machine code with no context isn't much to work with!

      Steve

      1 Reply Last reply
      0
      • T Tydia kun

        This really bothers me. See, I have a class and two variables of the same class, CBuffer, named Buffer and RetBuf. So, there's a line of code that says Buffer = RetBuf (class CBuffer has an overloaded operator = that takes another CBuffer& as argument). So even in debug, the compiler generates the following code: 004B1E48 mov eax,dword ptr [ebp+18h] 004B1E4B mov dword ptr [ebp+10h],eax 004B1E4E mov ecx,dword ptr [ebp+1Ch] 004B1E51 mov dword ptr [ebp+14h],ecx WHICH IS COMPLETELY WRONG! Does anyone know why this may happen and how to fix such a thing? I already tried a rebuild without success. All we long-time developers should know that unless there's an overload that takes a CBuffer& as argument, this operation is impossible. But there is one such overload, though, although the compiler does not generate code to call it, but instead perform pointer assigns! It's like it's thinking they're pointers, and therefore trying to assign the RetBuf pointer to the Buffer pointer, which again is not possible since there's no cast and they're different types! This boggles my mind! What IS the compiler doing?!

        M Offline
        M Offline
        Maximilien
        wrote on last edited by
        #3

        What led you to the conclusion that your code was wrongly compiled ? Was it not doing what you wanted ? Can we see the C++ code ?


        Maximilien Lincourt Your Head A Splode - Strong Bad

        T 1 Reply Last reply
        0
        • M Maximilien

          What led you to the conclusion that your code was wrongly compiled ? Was it not doing what you wanted ? Can we see the C++ code ?


          Maximilien Lincourt Your Head A Splode - Strong Bad

          T Offline
          T Offline
          Tydia kun
          wrote on last edited by
          #4

          What indeed? That it doesn't call the overloaded operator function is quite enough. Showing all the code would be pretty long and boring and irrelevant, so I'll show the important snippets of the declaration/definition of the variables and the class. template< class T1, class T2> long GetRegValuePtrNew(const char* strKey, const char* strName, CBuffer< T1> Buffer, /*bool bUseTempBuffer, */CBuffer< T2> RetBuf = (T2*)THROW_ERROR, DWORD* pType = NULL) throw(...) { ... Buffer = RetBuf; ... } template< typename T> class CBuffer { ... template< typename T2> void operator = (CBuffer< T2>& rBuffer); ... }; There's the basic declaration, so the obvious thing is that the compiler should generate code that calls CBuffer::operator =, but it doesn't, as you can see from the asm snippet I gave you. This is all the relevant parts of the code, but I can post the whole function/class if it's necessary. It's just that it would be so long. I also want to made it clear that I intentionally put spaces after a < since otherwise it's interpreted as HTML code and not shown. In REAL code I would NEVER do that, since I HATE it, it looks POOR. Just wanted to say that ;) EDIT: Actually, I seem to have fixed the problem. The problem was that the compiler was confused, but it still shouldn't have generated faulty code. It should complain, should it not? Consider this: As you saw above, the assignment operator takes a CBuffer of a DIFFERENT type than the type of the actual class (it takes T2 instead of T). In the above template, T1 and T2 = UINT64, the same type. Adding the following: void operator = (CBuffer& rBuffer); ...Fixes the problem. It seems the compiler gets confused and cannot interpret T2 as T (so if there's a var of CBuffer< UINT64>, the assignment operator can't take a CBuffer< UINT64> as argument, because it's the same type as the class type T). I got around it by adding an additional operator that takes the class's type T (CBuffer< T>) as argument and now it works. Of course, this shouldn't really be, AFAIK. Here is the new code: void operator = (CBuffer& rBuffer) { Assign(rBuffer); } template void operator = (CBuffer& rBuffer) { Assign(rBuffer); } template void Assign(CBuffer& rBuffer)... As plainly visible, both overloads call Assign, which takes a new template type T2 as argument, and both functions (well, I only tested the first, though) call the Assign fu

          L J 2 Replies Last reply
          0
          • T Tydia kun

            What indeed? That it doesn't call the overloaded operator function is quite enough. Showing all the code would be pretty long and boring and irrelevant, so I'll show the important snippets of the declaration/definition of the variables and the class. template< class T1, class T2> long GetRegValuePtrNew(const char* strKey, const char* strName, CBuffer< T1> Buffer, /*bool bUseTempBuffer, */CBuffer< T2> RetBuf = (T2*)THROW_ERROR, DWORD* pType = NULL) throw(...) { ... Buffer = RetBuf; ... } template< typename T> class CBuffer { ... template< typename T2> void operator = (CBuffer< T2>& rBuffer); ... }; There's the basic declaration, so the obvious thing is that the compiler should generate code that calls CBuffer::operator =, but it doesn't, as you can see from the asm snippet I gave you. This is all the relevant parts of the code, but I can post the whole function/class if it's necessary. It's just that it would be so long. I also want to made it clear that I intentionally put spaces after a < since otherwise it's interpreted as HTML code and not shown. In REAL code I would NEVER do that, since I HATE it, it looks POOR. Just wanted to say that ;) EDIT: Actually, I seem to have fixed the problem. The problem was that the compiler was confused, but it still shouldn't have generated faulty code. It should complain, should it not? Consider this: As you saw above, the assignment operator takes a CBuffer of a DIFFERENT type than the type of the actual class (it takes T2 instead of T). In the above template, T1 and T2 = UINT64, the same type. Adding the following: void operator = (CBuffer& rBuffer); ...Fixes the problem. It seems the compiler gets confused and cannot interpret T2 as T (so if there's a var of CBuffer< UINT64>, the assignment operator can't take a CBuffer< UINT64> as argument, because it's the same type as the class type T). I got around it by adding an additional operator that takes the class's type T (CBuffer< T>) as argument and now it works. Of course, this shouldn't really be, AFAIK. Here is the new code: void operator = (CBuffer& rBuffer) { Assign(rBuffer); } template void operator = (CBuffer& rBuffer) { Assign(rBuffer); } template void Assign(CBuffer& rBuffer)... As plainly visible, both overloads call Assign, which takes a new template type T2 as argument, and both functions (well, I only tested the first, though) call the Assign fu

            L Offline
            L Offline
            Lost User
            wrote on last edited by
            #5

            Tydia-kun wrote:

            CBuffer< T1> Buffer

            Tydia-kun wrote:

            CBuffer< T2> RetBuf

            Tydia-kun wrote:

            Buffer = RetBuf;

            Buffer and RetBuf are different types

            T 1 Reply Last reply
            0
            • T Tydia kun

              What indeed? That it doesn't call the overloaded operator function is quite enough. Showing all the code would be pretty long and boring and irrelevant, so I'll show the important snippets of the declaration/definition of the variables and the class. template< class T1, class T2> long GetRegValuePtrNew(const char* strKey, const char* strName, CBuffer< T1> Buffer, /*bool bUseTempBuffer, */CBuffer< T2> RetBuf = (T2*)THROW_ERROR, DWORD* pType = NULL) throw(...) { ... Buffer = RetBuf; ... } template< typename T> class CBuffer { ... template< typename T2> void operator = (CBuffer< T2>& rBuffer); ... }; There's the basic declaration, so the obvious thing is that the compiler should generate code that calls CBuffer::operator =, but it doesn't, as you can see from the asm snippet I gave you. This is all the relevant parts of the code, but I can post the whole function/class if it's necessary. It's just that it would be so long. I also want to made it clear that I intentionally put spaces after a < since otherwise it's interpreted as HTML code and not shown. In REAL code I would NEVER do that, since I HATE it, it looks POOR. Just wanted to say that ;) EDIT: Actually, I seem to have fixed the problem. The problem was that the compiler was confused, but it still shouldn't have generated faulty code. It should complain, should it not? Consider this: As you saw above, the assignment operator takes a CBuffer of a DIFFERENT type than the type of the actual class (it takes T2 instead of T). In the above template, T1 and T2 = UINT64, the same type. Adding the following: void operator = (CBuffer& rBuffer); ...Fixes the problem. It seems the compiler gets confused and cannot interpret T2 as T (so if there's a var of CBuffer< UINT64>, the assignment operator can't take a CBuffer< UINT64> as argument, because it's the same type as the class type T). I got around it by adding an additional operator that takes the class's type T (CBuffer< T>) as argument and now it works. Of course, this shouldn't really be, AFAIK. Here is the new code: void operator = (CBuffer& rBuffer) { Assign(rBuffer); } template void operator = (CBuffer& rBuffer) { Assign(rBuffer); } template void Assign(CBuffer& rBuffer)... As plainly visible, both overloads call Assign, which takes a new template type T2 as argument, and both functions (well, I only tested the first, though) call the Assign fu

              J Offline
              J Offline
              John R Shaw
              wrote on last edited by
              #6

              You do have some other problems you need to address. The argument to your overloaded method should be constant and it should return a reference to the left hand side of the argument so you can do things like: “a1 = a2 = a3”. Keep your eyes open for implicit conversions, which is what you’re originally problem sounded like.

              INTP "Program testing can be used to show the presence of bugs, but never to show their absence."Edsger Dijkstra

              T 1 Reply Last reply
              0
              • L Lost User

                Tydia-kun wrote:

                CBuffer< T1> Buffer

                Tydia-kun wrote:

                CBuffer< T2> RetBuf

                Tydia-kun wrote:

                Buffer = RetBuf;

                Buffer and RetBuf are different types

                T Offline
                T Offline
                Tydia kun
                wrote on last edited by
                #7

                Yes, they are and that's the whole point of the overloaded assignment operator (=). It takes a CBuffer of different type (or the same type) and copies the data from that buffer into its own buffer. But somehow the compiler didn't understand that.

                M L 2 Replies Last reply
                0
                • J John R Shaw

                  You do have some other problems you need to address. The argument to your overloaded method should be constant and it should return a reference to the left hand side of the argument so you can do things like: “a1 = a2 = a3”. Keep your eyes open for implicit conversions, which is what you’re originally problem sounded like.

                  INTP "Program testing can be used to show the presence of bugs, but never to show their absence."Edsger Dijkstra

                  T Offline
                  T Offline
                  Tydia kun
                  wrote on last edited by
                  #8

                  Constant? As in non-template function? If that's the case, that's a no-go. I also added a return type of CBuffer& to return *this, so it should work with a=b=c now, I think.

                  1 Reply Last reply
                  0
                  • T Tydia kun

                    Yes, they are and that's the whole point of the overloaded assignment operator (=). It takes a CBuffer of different type (or the same type) and copies the data from that buffer into its own buffer. But somehow the compiler didn't understand that.

                    M Offline
                    M Offline
                    Maximilien
                    wrote on last edited by
                    #9

                    Don't you need to implement template specialisatioin for that ?


                    Maximilien Lincourt Your Head A Splode - Strong Bad

                    T 1 Reply Last reply
                    0
                    • M Maximilien

                      Don't you need to implement template specialisatioin for that ?


                      Maximilien Lincourt Your Head A Splode - Strong Bad

                      T Offline
                      T Offline
                      Tydia kun
                      wrote on last edited by
                      #10

                      Templates are templates - they can be of any type. That's why the overloaded assignment operator takes a new template type of T2. That's the power of templates.

                      M 1 Reply Last reply
                      0
                      • T Tydia kun

                        Templates are templates - they can be of any type. That's why the overloaded assignment operator takes a new template type of T2. That's the power of templates.

                        M Offline
                        M Offline
                        Maximilien
                        wrote on last edited by
                        #11

                        what if you have

                        CBuffer<string> bufferOfString;
                        CBuffer<int> bufferofInt;

                        bufferOfString = bufferOfInt; // ????/

                        don't you need specialisation to know how to convert a CBuffer<int> to a CBuffer<string> ? It's not just a memcpy or member-member copy. I'm just curious, I'm not very familiar with template constructs.


                        Maximilien Lincourt Your Head A Splode - Strong Bad

                        T 1 Reply Last reply
                        0
                        • M Maximilien

                          what if you have

                          CBuffer<string> bufferOfString;
                          CBuffer<int> bufferofInt;

                          bufferOfString = bufferOfInt; // ????/

                          don't you need specialisation to know how to convert a CBuffer<int> to a CBuffer<string> ? It's not just a memcpy or member-member copy. I'm just curious, I'm not very familiar with template constructs.


                          Maximilien Lincourt Your Head A Splode - Strong Bad

                          T Offline
                          T Offline
                          Tydia kun
                          wrote on last edited by
                          #12

                          That wouldn't work unless you overlord a operator = (CBuffer<int>) or simply make a template operator = such as template<typename T2> operator = (CBuffer<T2>). That way, the compiler can call the overloaded operator = and pass bufferOfInt to it with T2 = int. Memcpy is a very stupid (and dangerous) way of assigning a class to another class since classes are built around handling its own memory and variables. If you read about templates, then you know that you can specify a type for a template and the compiler will generate a function with that type when the template function is invoked. Take for example template<typename T2> operator = (CBuffer<T2>) When you do bufferOfString = bufferOfInt, it generates an overloaded function operator = (CBuffer<int>) And calls it. That's it.

                          1 Reply Last reply
                          0
                          • T Tydia kun

                            Yes, they are and that's the whole point of the overloaded assignment operator (=). It takes a CBuffer of different type (or the same type) and copies the data from that buffer into its own buffer. But somehow the compiler didn't understand that.

                            L Offline
                            L Offline
                            Lost User
                            wrote on last edited by
                            #13

                            Tydia-kun wrote:

                            Yes, they are and that's the whole point of the overloaded assignment operator (=).

                            No its not. The point of the assignment operator is to assign the value of one object to the value of another. For that to be possible the objects have to be of the same type. Templates are nothing but code generation. When you declare vector and vector they are completely differnt types and have no common interface. If you want to perforam assignment between the two you have to write a specific operator. You cannt write a generic one

                            T 1 Reply Last reply
                            0
                            • L Lost User

                              Tydia-kun wrote:

                              Yes, they are and that's the whole point of the overloaded assignment operator (=).

                              No its not. The point of the assignment operator is to assign the value of one object to the value of another. For that to be possible the objects have to be of the same type. Templates are nothing but code generation. When you declare vector and vector they are completely differnt types and have no common interface. If you want to perforam assignment between the two you have to write a specific operator. You cannt write a generic one

                              T Offline
                              T Offline
                              Tydia kun
                              wrote on last edited by
                              #14

                              It's the whole point of MY overload operator =, I meant.

                              1 Reply Last reply
                              0
                              Reply
                              • Reply as topic
                              Log in to reply
                              • Oldest to Newest
                              • Newest to Oldest
                              • Most Votes


                              • Login

                              • Don't have an account? Register

                              • Login or register to search.
                              • First post
                                Last post
                              0
                              • Categories
                              • Recent
                              • Tags
                              • Popular
                              • World
                              • Users
                              • Groups