Note that there are some explanatory texts on larger screens.

plurals
  1. PODual emission of constructor symbols
    primarykey
    data
    text
    <p>Today, I discovered a rather interesting thing about either <code>g++</code> or <code>nm</code>...constructor definitions appear to have two entries in libraries.</p> <p>I have a header <code>thing.hpp</code>:</p> <pre><code>class Thing { Thing(); Thing(int x); void foo(); }; </code></pre> <p>And <code>thing.cpp</code>:</p> <pre><code>#include "thing.hpp" Thing::Thing() { } Thing::Thing(int x) { } void Thing::foo() { } </code></pre> <p>I compile this with:</p> <pre><code>g++ thing.cpp -c -o libthing.a </code></pre> <p>Then, I run <code>nm</code> on it:</p> <pre><code>%&gt; nm -gC libthing.a 0000000000000030 T Thing::foo() 0000000000000022 T Thing::Thing(int) 000000000000000a T Thing::Thing() 0000000000000014 T Thing::Thing(int) 0000000000000000 T Thing::Thing() U __gxx_personality_v0 </code></pre> <p>As you can see, both of the constructors for <code>Thing</code> are listed with two entries in the generated static library. My <code>g++</code> is 4.4.3, but the same behavior happens in <code>clang</code>, so it isn't just a <code>gcc</code> issue.</p> <p>This doesn't cause any apparent problems, but I was wondering:</p> <ul> <li>Why are defined constructors listed twice?</li> <li>Why doesn't this cause "multiple definition of symbol __" problems?</li> </ul> <hr> <p><strong>EDIT</strong>: For Carl, the output without the <code>C</code> argument:</p> <pre><code>%&gt; nm -g libthing.a 0000000000000030 T _ZN5Thing3fooEv 0000000000000022 T _ZN5ThingC1Ei 000000000000000a T _ZN5ThingC1Ev 0000000000000014 T _ZN5ThingC2Ei 0000000000000000 T _ZN5ThingC2Ev U __gxx_personality_v0 </code></pre> <p>As you can see...the same function is generating multiple symbols, which is still quite curious.</p> <p>And while we're at it, here is a section of generated assembly:</p> <pre><code>.globl _ZN5ThingC2Ev .type _ZN5ThingC2Ev, @function _ZN5ThingC2Ev: .LFB1: .cfi_startproc .cfi_personality 0x3,__gxx_personality_v0 pushq %rbp .cfi_def_cfa_offset 16 movq %rsp, %rbp .cfi_offset 6, -16 .cfi_def_cfa_register 6 movq %rdi, -8(%rbp) leave ret .cfi_endproc .LFE1: .size _ZN5ThingC2Ev, .-_ZN5ThingC2Ev .align 2 .globl _ZN5ThingC1Ev .type _ZN5ThingC1Ev, @function _ZN5ThingC1Ev: .LFB2: .cfi_startproc .cfi_personality 0x3,__gxx_personality_v0 pushq %rbp .cfi_def_cfa_offset 16 movq %rsp, %rbp .cfi_offset 6, -16 .cfi_def_cfa_register 6 movq %rdi, -8(%rbp) leave ret .cfi_endproc </code></pre> <p>So the generated code is...well...the same.</p> <hr> <p><strong>EDIT</strong>: To see what constructor actually gets called, I changed <code>Thing::foo()</code> to this:</p> <pre><code>void Thing::foo() { Thing t; } </code></pre> <p>The generated assembly is:</p> <pre><code>.globl _ZN5Thing3fooEv .type _ZN5Thing3fooEv, @function _ZN5Thing3fooEv: .LFB550: .cfi_startproc .cfi_personality 0x3,__gxx_personality_v0 pushq %rbp .cfi_def_cfa_offset 16 movq %rsp, %rbp .cfi_offset 6, -16 .cfi_def_cfa_register 6 subq $48, %rsp movq %rdi, -40(%rbp) leaq -32(%rbp), %rax movq %rax, %rdi call _ZN5ThingC1Ev leaq -32(%rbp), %rax movq %rax, %rdi call _ZN5ThingD1Ev leave ret .cfi_endproc </code></pre> <p>So it is invoking the complete object constructor.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload