我的C ++对象文件太大了

时间:2009-01-22 19:01:05

标签: c++ compiler-optimization filesize object-files

我正在开发一个C ++程序,来自单个1200行文件(初始化一个相当复杂的状态机)的编译目标代码几乎达到了一兆字节。什么可以使文件这么大?有没有办法找到在目标文件中占用空间的东西?

7 个答案:

答案 0 :(得分:9)

当目标文件大于最小值时,可能有几个原因:

  • 静态包含依赖库
  • 使用调试信息构建
  • 使用分析信息构建
  • 使用模板创建(非常)复杂的数据结构(可能是递归的boost结构)
  • 在编译时没有打开优化标记(保存不那么多,如果使用得太厉害会导致困难)

首先,我建议您检查一下是否使用调试信息进行构建,这会导致我的体验最为臃肿。

答案 1 :(得分:7)

(我假设你已经进行了优化并且打开了死代码剥离)。

打开链接器的“生成地图文件”选项并检查输出。

常见的罪魁祸首是产生大量代码和大型全局对象的宏/模板。

答案 2 :(得分:5)

可能是一些模板实例化(尤其是std::iostream s),也可能是大量的内联(即在标题中完全定义的类)。但是,首先是1兆字节的目标文件有什么问题?在链接期间,它可能会产生一个很小的二进制文件。我在这里得到了一个项目,其中包含20 MiB的目标文件,例如链接到700 KiB二进制文件。

更新:也可能是一些大的静态数组/对象。除此之外,使用MSVC ++和GCC,您可以查看生成的文件的程序集,它可以为您提供一些提示(使用GCC,它是g++ -S foo.cpp,对于MSVC ++,它是'/FAs')。要么你会看到很多模板实例,那么这就是原因。如果不是,那就是static个对象的对象大小。

答案 3 :(得分:0)

另一个可能的原因是链接时代码生成,VC ++选项。这会将编译器的后端移动到链接器中。这允许更好的优化,但是目标文件现在必须包含通常在前端和后端之间传递的所有内部数据结构。

答案 4 :(得分:0)

一个不错的选择就是看看Tool to analyze size of ELF sections and symbol中提到的可能性,例如:

nm -C --print-size --size-sort --radix=d tst.o
size -A -d tst.o | sort -k2 -n

我见过在C ++中调试符号为MASSIVE的情况,例如30x larger than the rest of the binary,因此,这绝对是要注意的事情之一,上述size命令会因大量与调试相关的部分而立即提示您,您可以使用{ {1}}或strip

要注意的另一件事是,您是否可以通过显式的模板实例化节省一些空间/时间:Explicit template instantiation - when is it used?的“如何快速分析构建以查看它是否可以从模板实例化中受益”部分该答案还包含在大型(C ++)项目中跨目标文件查找重复对象的方法。

答案 5 :(得分:0)

您可以通过添加编译标志-flto -Wl,-allow-multiple-definition来添加-fuse-linker-plugin-Wa,-mbig-obj在x86 / 32位体系结构(仅x64)上不起作用

答案 6 :(得分:-3)

这是我用来查看编译时间值的宏:

template <size_t N> struct compile_time_number { private: typedef int check; };
#define compiler_check_number(N) ((compile_time_number< N >::check)0)

然后在编译时感到高兴,看看哪些符号占用了空间。

编辑:由于似乎没有人理解这一点,我将澄清:使用它的方法是添加compiler_check_number(sizeof(<insert struct or global variable here>))。编译器将吐出变量或结构的大小作为编译时错误。很少有代码是一个巨大的目标文件的原因。

我总是使用它来查看有多大的东西,而无需运行调试器。