Reputation: 8047
I've got 2 cpp files, each declared 1 class+1 function+1 static object:
$ cat mya.cpp
#include<stdio.h>
struct A{
A(){printf("%s\n",__FUNCTION__);}
};
void fa(){printf("%s\n",__FUNCTION__);}
static A s_obj;
$ cat myb.cpp
#include<stdio.h>
struct B{
B(){printf("%s\n",__FUNCTION__);}
};
void fb(){printf("%s\n",__FUNCTION__);}
static B s_obj;
Then main function calls "fb", but not "fa".
$ cat nm.cpp
void fb();
int main()
{
fb();
return 0;
}
I tried to compile and link these files in different ways:
g++ -c mya.cpp -fPIC
g++ -c myb.cpp -fPIC
ar -rvs libmya.a mya.o
ar -rvs libmyb.a myb.o
ar -rvs libmystatic.a mya.o myb.o
g++ --shared -o libmyshare.so mya.o myb.o
g++ --shared -o libadyn.so mya.o
g++ --shared -o libbdyn.so myb.o
g++ nm.cpp -o use1StaticLib -lmystatic -L.
g++ nm.cpp -o use2StaticLib -lmyb -lmya -L.
g++ nm.cpp -o use1DynamicLib -lmyshare -L.
g++ nm.cpp -o use2DynamicLib -ladyn -lbdyn -L.
g++ nm.cpp -o useDirect mya.cpp myb.cpp
Then I found the 5 executables have different behavior:
$ ./useDirect
A
B
fb
$ ./use1DynamicLib
A
B
fb
$ ./use2DynamicLib
B
fb
$ ./use1StaticLib
A
B
fb
$ ./use2StaticLib
B
fb
Same code, different behavior, how can I not be confused?
I seem to find some clue, as long as mya.cpp and myb.cpp are packaged into different .a/.so file, then "A s_obj" is not constructed. Why? Constructor of A has side effect, and I'm not specifying any -O optimization.
If the reason is that "A s_obj" is an object that's not used, so not linked, then, "B s_obj" is neither used by main function, why it's always constructed?
Need to hear from your experts' explanations!
Upvotes: 3
Views: 72
Reputation: 312
I think there are 2 effects here that needs to be distinguish
First, when you make calls to external libraries, the dynamic linker is lazy and will only load libraries that are actually called. But it will load the whole library. With use2StaticLib
, you are only using the lib b so it will load only this one. The same goes for use2DynamicLib
Second, writing this:
g++ --shared -o libmyshare.so mya.o myb.o
is the same as using
g++ --shared -o libmyshare.so myfile.o
where myfile.cpp is a concatenation of mya.cpp
and myb.cpp
You are just copying two object files into a bigger one libmyshare.so
so that is why when you call one function of the myb.cpp
file, the application load the entire libmyshare.so
library. The constructors of A and B are then called in this case to initiliaze the static objects. This do not change whether the compilation of libmyshare.so
is static or dynamic.
In any of these scenarios, the code of the libA and libB are included into your application code (even when compiled statically) and all the libs are called through dynamic linking.
Hope this help !
Upvotes: 2