Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>First, you should generally use <code>-fPIC</code> flag when building shared libraries.</p> <p>Not using it "works" on 32-bit Linux, but would fail on 64-bit one with an error similar to:</p> <pre><code>/usr/bin/ld: /tmp/ccUUrz9c.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC </code></pre> <p>Second, your program will work as you expect after you add <code>-rdynamic</code> to the link line for the main executable:</p> <pre><code>singleton.num in main : 100 singleton.num in hello.so : 100 singleton.num in hello.so after ++ : 101 singleton.num in main : 101 </code></pre> <p>In order to understand why <code>-rdynamic</code> is required, you need to know about the way dynamic linker resolves symbols, and about the <em>dynamic</em> symbol table.</p> <p>First, let's look at the dynamic symbol table for <code>hello.so</code>:</p> <pre><code>$ nm -C -D hello.so | grep singleton 0000000000000b8c W singleton::instance() 0000000000201068 B singleton::pInstance 0000000000000b78 W singleton::singleton() </code></pre> <p>This tells us that there are two weak function definitions, and one global variable <code>singleton::pInstance</code> that are visible to the dynamic linker.</p> <p>Now let's look at the static and dynamic symbol table for the original <code>example1</code> (linked without <code>-rdynamic</code>):</p> <pre><code>$ nm -C example1 | grep singleton 0000000000400d0f t global constructors keyed to singleton::pInstance 0000000000400d38 W singleton::instance() 00000000006022e0 B singleton::pInstance 0000000000400d24 W singleton::singleton() $ nm -C -D example1 | grep singleton $ </code></pre> <p>That's right: even though the <code>singleton::pInstance</code> is present in the executable as a global variable, that symbol is not present in the <em>dynamic</em> symbol table, and therefore "invisible" to the dynamic linker.</p> <p>Because the dynamic linker "doesn't know" that <code>example1</code> already contains a definition of <code>singleton::pInstance</code>, it doesn't bind that variable inside <code>hello.so</code> to the existing definition (which is what you really want).</p> <p>When we add <code>-rdynamic</code> to the link line:</p> <pre><code>$ nm -C example1-rdynamic | grep singleton 0000000000400fdf t global constructors keyed to singleton::pInstance 0000000000401008 W singleton::instance() 00000000006022e0 B singleton::pInstance 0000000000400ff4 W singleton::singleton() $ nm -C -D example1-rdynamic | grep singleton 0000000000401008 W singleton::instance() 00000000006022e0 B singleton::pInstance 0000000000400ff4 W singleton::singleton() </code></pre> <p>Now the definition of <code>singleton::pInstance</code> inside the main executable is <em>visible</em> to the dynamic linker, and so it will "reuse" that definition when loading <code>hello.so</code>:</p> <pre><code>LD_DEBUG=bindings ./example1-rdynamic |&amp; grep pInstance 31972: binding file ./hello.so [0] to ./example1-rdynamic [0]: normal symbol `_ZN9singleton9pInstanceE' </code></pre>
 

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