【问题标题】:How does (boost like) header only libraries influence compilation size?(boost like) 仅标头库如何影响编译大小?
【发布时间】:2014-12-23 10:38:07
【问题描述】:

当我在两个翻译单元中包含 boost 库 hpp 标头时,boost 代码是否编译两次(与传统的预编译库相比,二进制大小是两倍?)?

【问题讨论】:

  • 只是谷歌“c++ 模板代码膨胀”。情况正在好转。
  • 这个问题无法真正回答:它在很大程度上取决于编译器/链接器,以及您是否针对速度或大小进行了优化。您不应该在最终程序中出现多个定义;但您最终可能会得到更多内联函数调用,这可能(也可能不会)增加程序大小。

标签: c++ boost compilation header-files precompile


【解决方案1】:

您提出了两个不同的问题:

boost 代码是否编译两次?是的,它确实。最终结果是编译时间可能会更长一些,因为编译器必须消化每个编译单元的所有头文件。

二进制大小是两倍?不,它可能不会,但这将归结为您选择的优化标志。在单元 A 中实例化的模板在概念上将与在单元 B 中实例化的具有完全相同类型参数的模板共享相同的实现代码。

它是否实际上共享相同的代码将取决于您的优化标志是否允许内联模板实现。如果您已允许内联并且编译器已选择这样做,那么您的二进制大小将随着编译器将模板实现与您的代码内联以实现您声明的优化目标而增加。

使用纯二进制库永远不可能内联,因此这是使用纯标头库时二进制大小可能会增长的原因之一。

下面是一个例子,展示了在未启用内联时 gcc 如何共享模板实现:

a.cpp

#include <vector>

void test1() {
  std::vector<int> myvec;
  myvec.push_back(1);
}

b.cpp

#include <vector>

void test2() {
  std::vector<int> myvec;
  myvec.push_back(1);
}

m.cpp

extern void test1(),test2();

main() {
  test1();
  test2();
}

编译

g++ -g -O0 -fno-inline -c m.cpp
g++ -g -O0 -fno-inline -c a.cpp
g++ -g -O0 -fno-inline -c b.cpp
g++ -o a.out a.o b.o m.o
objdump -S a.out |less

objdump分析

void test1() {
  // [snip]
  myvec.push_back(1);
  // [snip]
  4008a0:       e8 d1 00 00 00          callq  400976 <_ZNSt6vectorIiSaIiEE9push_backERKi>

void test2() {
  // [snip]
  myvec.push_back(1);
  // [snip]
  401548:       e8 29 f4 ff ff          callq  400976 <_ZNSt6vectorIiSaIiEE9push_backERKi>

请注意如何使用 push_back 的相同实现(位置 400976),即使它被编译成完全独立的编译单元。

【讨论】:

  • 谢谢!如果编译器可以检测到代码重复,这是一个了不起的功能!
  • @user2449761 大声笑,模板已经存在了几十年,没有那么神奇的功能。
  • @user2449761 它是通过命名和链接完成的。所有内联方法都具有弱链接,并且由于名称修饰对所有参数进行编码,因此名称最终相同,并且链接器仅选择一个。
【解决方案2】:

有些 boost 头文件特别大(我在看你的 boost/lexical_cast.hpp),这会导致二进制文件变大。但是,编译器提供了一些帮助选项:

MSVC 有一个选项 /LTCG(链接时代码生成)

GCC 有 -flto(我相信是用 -O3 启用的)

这些选项通常允许链接器丢弃未使用的组件并减少跨编译单元的重复。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-02-20
    • 1970-01-01
    • 2020-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多