【问题标题】:C++ differ between Linking with .o and with .a file: different behavior, why?C++ 与 .o 和 .a 文件链接之间的区别:不同的行为,为什么?
【发布时间】:2016-12-28 15:08:02
【问题描述】:

我预计:

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

但事实并非如此。我有 2 个源文件,每个文件声明 1class+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”文件和链接从这 2 个“.o”文件存档的“.a”文件之间有什么区别。

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

这种差异是怎么来的?

【问题讨论】:

  • 链接器只会使用库中的目标文件,这些文件实际上是满足某些外部引用所需要的;那些没有以任何方式引用的被忽略,全局变量和所有。大多数时候你都希望这样 - 一个大型静态库通常包含比给定程序所需的更多代码,你不希望整个东西与你的可执行文件链接,所以它最终包含很多死的,从未使用过的代码。

标签: c++ static linker shared behavior


【解决方案1】:

这是由于静态库的语义。链接器只会包含静态库中的文件,前提是它包含在命令行中被位于它之前的某个目标文件引用的符号(例如 main.cpp 从 Second 引用 f2 ,因此它被包含在内)。你可以用包围你的库来覆盖这个行为

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

但这不是标准的。

【讨论】:

  • Bingo,这是我正在寻找提供“ld”的选项,它可以明确链接到所有内容。
猜你喜欢
  • 1970-01-01
  • 2011-08-19
  • 2015-07-23
  • 1970-01-01
  • 2012-05-15
  • 1970-01-01
  • 2019-04-12
  • 2010-12-21
  • 2017-05-19
相关资源
最近更新 更多