Why does my manual constructor copy code other than standard?

I tried to find the answer to a question I had some time ago ( Automatically detect if a user-defined function is equivalent to implicit ). My thought was that I would compile the copy constructor, and then parse the code and verify that they are identical. Code:

struct A
{
    int B;
    A() : B(0) { }
#ifdef COPY_CONSTRUCTOR
    A(const A& a) : B(a.B) { }
#endif
};

#include <stdio.h>
int main()
{
    A a;
    A b(a);
    printf("%d", b.B);
}

Compiled using (cygwin gcc v4.9.3):

gcc -o a1.exe main.cpp -std=c++11 -g -O0 -DCOPY_CONSTRUCTOR
gcc -o a2.exe main.cpp -std=c++11 -g -O0 -fno-elide-constructors

And then resetting the disassembly, copy constructors ( _ZN1AC1ERKS_- the distorted name of the copy constructor):

gdb -batch -ex 'file a1.exe' -ex 'disass _ZN1AC1ERKS_'

It produces:

Dump of assembler code for function A::A(A const&):
   0x0000000100401770 <+0>:     push   %rbp
   0x0000000100401771 <+1>:     mov    %rsp,%rbp
   0x0000000100401774 <+4>:     mov    %rcx,0x10(%rbp)
   0x0000000100401778 <+8>:     mov    %rdx,0x18(%rbp)
   0x000000010040177c <+12>:    mov    0x18(%rbp),%rax
   0x0000000100401780 <+16>:    mov    (%rax),%edx
   0x0000000100401782 <+18>:    mov    0x10(%rbp),%rax
   0x0000000100401786 <+22>:    mov    %edx,(%rax)
   0x0000000100401788 <+24>:    pop    %rbp
   0x0000000100401789 <+25>:    retq
End of assembler dump.

and

gdb -batch -ex 'file a2.exe' -ex 'disass _ZN1AC1ERKS_'

It produces:

Dump of assembler code for function A::A(A const&):
   0x0000000100401770 <+0>:     push   %rbp
   0x0000000100401771 <+1>:     mov    %rsp,%rbp
   0x0000000100401774 <+4>:     mov    %rcx,0x10(%rbp)
   0x0000000100401778 <+8>:     mov    %rdx,0x18(%rbp)
   0x000000010040177c <+12>:    mov    0x10(%rbp),%rax
   0x0000000100401780 <+16>:    mov    0x18(%rbp),%rdx
   0x0000000100401784 <+20>:    mov    (%rdx),%edx
   0x0000000100401786 <+22>:    mov    %edx,(%rax)
   0x0000000100401788 <+24>:    pop    %rbp
   0x0000000100401789 <+25>:    retq
End of assembler dump.

They are the same, except that the string mov 0x10(%rbp),%raxoccurs in a different order. In this case, it is harmless, but, obviously, makes the detection of equivalence more difficult. What is the explanation for the differences?

+6
1

, . 1 2 , .

!

:

.LC0:
        .string "%d"
Test():
        push    0
        push    OFFSET FLAT:.LC0
        call    printf
        pop     eax
        pop     edx
        push    0
        push    OFFSET FLAT:.LC0
        call    printf
        pop     ecx
        pop     eax
        ret

, , , , gcc.

Visual Studio :

int main()
{
    A a;
    A b(a);
    printf("%d", b.B);
00B41000  push        0  
00B41002  push        0B499A0h  
00B41007  call        printf (0B4102Dh)  
    printf("%d", a.B);
00B4100C  push        0  
00B4100E  push        0B499A4h  
00B41013  call        printf (0B4102Dh)  
00B41018  add         esp,10h  
    return 0;
0127101B  xor         eax,eax  
}
0127101D  ret  
0

Source: https://habr.com/ru/post/1015535/


All Articles