2016-12-27 94 views
3

我有2个cpp文件,每个申报1级+ 1个功能+ 1个的静态对象:相同的C++代码,不同的链接选项导致不同的行为?

$ 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; 

然后主函数调用 “FB”,而不是 “发”。

$ 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文件中,则“A s_obj”不会被构建。为什么? A的构造函数有副作用,我没有指定任何-O优化。

如果原因是“A s_obj”是一个未使用的对象,所以没有链接,那么,“B s_obj”既不被主函数使用,它为什么总是被构造?

需要听取专家的解释!

+0

全局构造函数不被依赖,但你已经知道了。这只是未定义的,可能是因为涉及语言和操作系统规则。 – Jojje

回答

2

我觉得这里有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,这就是为什么当你调用的一个函数时文件,应用程序加载整个libmyshare.so库。在这种情况下,调用A和B的构造函数来启动静态对象。这不会改变libmyshare.so的编译是静态的还是动态的。

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

希望得到这个帮助!

相关问题