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

标签 c++ static linker shared behavior

我预计:

linking with .o file, and linking with .a file archived from the .o file, should have no difference.

但事实并非如此。我有 2 个源文件,每个都声明 1class+1 static object+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) The running result of MylinkSta doesn't construct 'First' object, but MyDirect does.

(2) While the 'Second' object is always constructed.

我真的看不出链接 2 个“.o”文件和链接从这 2 个“.o”文件归档的“.a”文件有什么区别。

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

这种差异是怎么来的?

最佳答案

这是由于静态库的语义。如果链接器包含由命令行中它前面的某个目标文件引用的符号,则链接器将仅包含来自静态库的文件(例如,main.cpp 引用来自 Second 的 f2,因此它被包含在内)。您可以使用

包围您的库来覆盖此行为
-Wl,--whole-archive -lmystatic -Wl,--no-whole-archive

但这不是标准的。

关于C++ 在使用 .o 和使用 .a 文件链接之间存在差异 : different behavior, 为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41364698/

相关文章:

c++ - 在 NDK 的稳定 API 之外使用原生 Android 系统库

c++ - 传递函数输出在 C 中不正确

c++ - GetLastInputInfo() 阻塞一个函数

c++ - 将 iostream 与 stdio 同步

java - Powermock:静态接口(interface)方法给出未完成的 stub 异常

python - 在 python 中,是否有与 isinstance 等效的静态?

java - 覆盖匿名类的 tostring

c++ - Gtest 无法在 mac 上使用默认编译器进行链接

linker - 使用 CMake 从静态库链接 Windows DLL 文件,而无需手工制作未解析的符号名称

C++ fork()、多线程和操作系统的概念