External linkage objects with constructors/destructors in shared libraries
09:24 30 Dec 2025

While answering this question I decided to check myself and did a little experiment. There are three files:

// moo.h
#ifndef MOO_H
#define MOO_H

#include 

struct Moo
{
    Moo() {
        std::cout << "Moo: " << static_cast(this) << "\n";
    }
    ~Moo() {
        std::cout << "~Moo: " << static_cast(this) << "\n";
    }
};

void dummy();

#endif
// libmoo.cpp
#include "moo.h"

Moo moo;

void dummy() {}
// main.cpp
#include "moo.h"

Moo moo;

int main()
{
    dummy();
}

I then built an executable and a shared library out of these.

g++ -shared -o libmoo.so moo.cpp -fPIC
g++ -o main main.cpp -L. -lmoo -Wl,-rpath=.

As expected, the two moo objects got merged and the ctor/dtor ran for it twice:

Moo: 0x5b923c8ee151
Moo: 0x5b923c8ee151
~Moo: 0x5b923c8ee151
~Moo: 0x5b923c8ee151    

Now, according to my own advice in my answer to that question, I rebuilt the shared library with -Bsymbolic, expecting that the two objects now will be separate and the program will print different addresses for them. To my astonishment, the addresses still were the same!

Moo: 0x607411e83151
Moo: 0x607411e83151
~Moo: 0x607411e83151
~Moo: 0x607411e83151

I tried different compiler and linker options, including -fno-weak -fno-inline-functions and -pie, but to no avail. The addresses were always the same.

What is going on here? Is there a way to build the library and/or the executable such that the objects are separate?

c++ shared-libraries