C++ 使用 .o 链接和使用 .a 文件链接之间存在差异:行为不同,为什么?

2024-02-21

我期望:

与 .o 文件链接和与从 .o 文件存档的 .a 文件链接应该没有区别。

但事实并非如此。我有2个源文件,每个都声明1个类+1个静态对象+1个函数,以及一个调用其中一个函数的main.cpp

$cat First.cpp
#include<stdio.h>
struct First{
  First(){printf("First\n");}
};
void f1(){printf("f1\n");}//Not called in main
static First f_obj;

$cat Second.cpp
#include<stdio.h>
struct Second{
  Second(){printf("Second\n");}
};
void f2(){printf("f2\n");}//Not called in main
static Second s_obj;

$cat main.cpp
void f2();
int main()
{
    f2();
    return 0;
}

$g++ -c First.cpp  -fPIC
$g++ -c Second.cpp -fPIC
$ar -rvs libmystatic.a  First.o Second.o
$g++ main.cpp -o MylinkSta -lmystatic -L.
$g++ main.cpp -o MyDirect First.o Second.o

$./MylinkSta
Second
f2

$./MyDirect
Second
First
f2

所以你可以看到

(1) MylinkSta 的运行结果没有构造 'First' 对象,但 MyDirect 构造了。

(2) 虽然“第二”对象始终被构造。

我确实没有看到链接 2 个“.o”文件和链接从这两个“.o”文件存档的“.a”文件之间有任何区别。

为什么他们的行为不同?我在 rhel/ubuntu 上用 gcc/clang 进行了实验,都显示了相同的结果。我想知道是否有任何 C++ ABI 标准规定何时应通过任何链接选项真正调用创建的静态/全局对象?

这种差异是怎么来的呢?


这是由于静态库的语义造成的。如果静态库中包含由命令行中位于其前面的某个目标文件引用的符号,则链接器将仅包含静态库中的文件(例如 main.cpp 引用 Second 中的 f2,因此包含它)。您可以通过围绕您的库来覆盖此行为

-Wl,--whole-archive -lmystatic -Wl,--no-whole-archive

但这不是标准的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 使用 .o 链接和使用 .a 文件链接之间存在差异:行为不同,为什么? 的相关文章

随机推荐