我有2个cpp文件,每个文件声明1个类+ 1个函数+ 1个静态对象:
$ 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;
然后主函数调用&#34; fb&#34;,但不是&#34; fa&#34;。
$ cat nm.cpp
void fb();
int main()
{
fb();
return 0;
}
我尝试以不同的方式编译和链接这些文件:
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
然后我发现5个可执行文件有不同的行为:
$ ./useDirect
A
B
fb
$ ./use1DynamicLib
A
B
fb
$ ./use2DynamicLib
B
fb
$ ./use1StaticLib
A
B
fb
$ ./use2StaticLib
B
fb
相同的代码,不同的行为,我怎能不混淆?
我似乎找到了一些线索,只要将mya.cpp和myb.cpp打包到不同的.a / .so文件中,然后&#34; A s_obj&#34;没有建造。为什么? A的构造函数有副作用,我没有指定任何-O优化。
如果原因是&#34; A s_obj&#34;是一个未被使用的对象,因此没有链接,然后,&#34; B s_obj&#34;主要功能既不使用它,为什么它总是被构造?
需要听取您的专家的意见&#39;解释!
答案 0 :(得分:2)
我认为这里有两个需要区分的效果
首先,当您调用外部库时,动态链接器是惰性的,只会加载实际调用的库。但它会加载整个库。使用use2StaticLib
,您只使用lib b,因此它只会加载这个。 use2DynamicLib
其次,写下这个:
g++ --shared -o libmyshare.so mya.o myb.o
与使用
相同 g++ --shared -o libmyshare.so myfile.o
其中myfile.cpp是mya.cpp
和myb.cpp
的串联你只是将两个目标文件复制到一个更大的libmyshare.so
中,这就是为什么当你调用{的一个函数时{1}}文件,应用程序加载整个myb.cpp
库。然后在这种情况下调用A和B的构造函数来初始化静态对象。这不会改变libmyshare.so
的编译是静态的还是动态的。
在任何这些场景中,libA和libB的代码都包含在应用程序代码中(即使是静态编译),并且所有的lib都是通过动态链接调用的。
希望这有帮助!