gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 21:35:51 27 4
gpt4 key购买 nike

我有 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;

然后主函数调用“fb”,而不是“fa”。

$ 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”也没有被main函数使用,为什么总是构造?

需要听取专家的解释!

最佳答案

我觉得这里有2个效果需要区分

首先,当您调用外部库时,动态链接器是惰性的,只会加载实际调用的库。但它会加载整个库。使用 use2StaticLib,您只使用库 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 这就是为什么当您调用 myb.cpp 文件的一个函数时,应用程序会加载整个 libmyshare.so 库。然后在这种情况下调用 A 和 B 的构造函数来初始化静态对象。这不会改变 libmyshare.so 的编译是静态的还是动态的。

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

希望对您有所帮助!

关于c++ - 相同的 C++ 代码,不同的链接选项会导致不同的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41348289/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com