2

The question is very similar to this one, however none of the solutions mentioned there was helpful.

Suppose I have a shared library B with a function that uses a local global variable. This function is called from a second shared library C.

Both B and C are used by A, and I would expect each to have its own instance of the global variable, but somehow the compiler manages to link them to point to the same object (unlike Windows).

Can someone suggest a method to allow me having to different instances of the global variable in A?

Below is my code. When running a.out, I'd expect to get

1
calling from someCFunc(): 1

However, I get:

1
calling from someCFunc(): 2

b.h:

#ifndef _B_H_
#define _B_H_

extern "C" __attribute__ ((visibility("default"))) void myFunc();

#endif

b.cpp:

#include "b.h"
#include <iostream>

int myGlobal = 0;

extern "C" __attribute__ ((visibility("default"))) void myFunc()
{
    ++myGlobal;
    std::cout << myGlobal << "\r\n";
}

c.h:

#ifndef _C_H_
#define _C_H_

extern "C" __attribute__ ((visibility("default"))) void someCFunc();

#endif

c.cpp

#include "c.h"
#include "b.h"
#include <iostream>

extern "C" __attribute__ ((visibility("default"))) void someCFunc()
{
    std::cout << "calling from someCFunc(): ";
    myFunc();
}

a.cpp:

#include "b.h"
#include "c.h"

int main(void)
{
    myFunc();
    someCFunc();

    return 0;
}

buildscript:

rm *.so
rm *.out
g++ -fPIC -fvisibility=hidden -shared b.cpp -o libb.so
g++ -fPIC -fvisibility=hidden -shared b.cpp -o libb2.so
g++ -fPIC -fvisibility=hidden -shared c.cpp -o libc.so -l:libb.so
g++ a.cpp -fPIC -fvisibility=hidden -l:libb2.so -l:libc.so
Community
  • 1
  • 1
Mark S
  • 235
  • 3
  • 11

1 Answers1

1

Both B and C are used by A, and I would expect each to have its own instance of the global variable

Your expectations are wrong. What you are observing here is the correct and expected behaviour. If what you expect was true, every single library out there would face a problem quite similar to the infamous diamond class hierarchy.

Can someone suggest a method to allow me having to different instances of the global variable in A?

As far as I know, this is not possible in C++. If you want to use different variables, you have to define them separately and pass a reference to your function:

// B
void myFunc(int& myVar) {
    ++myVar;
    std::cout << myVar << "\r\n";
}

// C
int myGlobalC = 0;
void someCFunc() {
    myFunc(myGlobalC);
}

// A
int myGlobalA = 0;
int main() {
    myFunc(myGlobalA);
    someCFunc();
}
syam
  • 14,701
  • 3
  • 41
  • 65
  • It is possible, since I do get the expected result when I run the code on with VS2010 (change __attribute__... to __declspec(dllexport))... There must be a way to mimic the same behaviour in linux – Mark S Aug 21 '13 at 16:20
  • Just to elaborate: From A's perspective, it uses two different libraries called b2 and c. it does not (and should not) expect their behavior to be linked in any way. suppose that b2 was built from a different source code (foo.cpp, foo.h) which happened to have a global integer named myGlobal, why should it be linked to the variable used by another library named c??!?? – Mark S Aug 21 '13 at 16:29
  • @MarkS My bad, I somehow overlooked the fact that you had two identical libraries named differently. Long story short: I'm afraid you can't do this on Linux since the runtime linker (library loader) does not handle symbols the same way as Windows. Conflicting symbols will be "overridden" by the latest loaded library. I don't have time right now for a detailed answer but I'll put one together as soon as I can. Maybe `dlopen` could help but this is kind of a hack. – syam Aug 21 '13 at 19:56