相同的C ++代码,不同的链接选项导致不同的行为?

时间:2016-12-27 16:00:08

标签: c++ linker libraries

我有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;解释!

1 个答案:

答案 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.cppmyb.cpp的串联你只是将两个目标文件复制到一个更大的libmyshare.so中,这就是为什么当你调用{的一个函数时{1}}文件,应用程序加载整个myb.cpp库。然后在这种情况下调用A和B的构造函数来初始化静态对象。这不会改变libmyshare.so的编译是静态的还是动态的。

在任何这些场景中,libA和libB的代码都包含在应用程序代码中(即使是静态编译),并且所有的lib都是通过动态链接调用的。

希望这有帮助!