我的 C++ 目标文件太大
我正在开发一个 C++ 程序,来自单个 1200 行文件(初始化一个相当复杂的状态机)的编译目标代码接近一兆字节。 是什么原因导致文件如此之大? 有没有办法找到目标文件中占用空间的内容?
I am working on a C++ program and the compiled object code from a single 1200-line file (which initializes a rather complex state machine) comes out to nearly a megabyte. What could be making the file so large? Is there a way I can find what takes space inside the object file?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
(我假设您已经打开了优化和死代码剥离)。
打开链接器的“生成映射文件”选项并检查输出。
常见的罪魁祸首是产生大量代码和大型全局对象的宏/模板。
(I'm assuming you've got optimisations and dead code stripping turned on).
Turn on your linker's "generate map file" option and examine the output.
Common culprits are macros/templates that produce large amounts of code, and large global objects.
可能是一些模板实例化(尤其是 std::iostream),也可能是广泛的内联(即在标头中完全定义的类)。 然而,1MB 的目标文件首先有什么问题呢? 在链接过程中,很可能会产生一个很小的二进制文件。 我在这里有一个项目,其中包含 20 MiB 的目标文件,例如链接到 700 KiB 的二进制文件。
更新:也可能是一些大型静态数组/对象。 除此之外,使用 MSVC++ 和 GCC,您可以查看文件生成的程序集,这可以给您一些提示(对于 GCC,它是
g++ -S foo.cpp
,对于 MSVC++,它是 '/FAs')。 要么您会看到很多模板实例,那么这就是原因。 如果不是,则它是静态对象的对象大小。Possibly some template instantiations (especially the
std::iostream
s), and maybe extensive inlining (i.e. classes which are fully defined in a header). However, what's the problem with a 1-megabyte object file in the first place? During linking, it might very well result in a tiny binary. I got a project here with 20 MiB of object files which gets linked into a 700 KiB binary for example.Update: Could be also some large static array/object. Besides that, with MSVC++ and GCC, you can look at the generated assembly for a file, which can give you some hints (with GCC, it's
g++ -S foo.cpp
, for MSVC++, it's '/FAs'). Either you will see a lot of template instances, then these are the reason. If not, it's the object size ofstatic
objects.另一个可能的原因是链接时代码生成,这是一个 VC++ 选项。 这会将编译器的后端移至链接器中。 这可以实现更好的优化,但目标文件现在必须包含通常在前端和后端之间传递的所有内部数据结构。
Another possible reason is Link-Time Code Generation, a VC++ option. This moves the backend of the compiler into the linker. This allows for better optimizations, but the object file now has to contain all internal datastructures usually passed between front- and backend.
一个不错的选择是看看 分析 ELF 部分和符号大小的工具 例如:
我见过 C++ 中调试符号很大的情况,例如 比二进制文件的其余部分大 30 倍,所以这绝对是需要注意的事情之一,上面的
size
命令会立即提示您由于与调试相关的部分巨大,您可以通过使用strip
或g++ -s
剥离二进制文件来进行双重检查。另一件需要注意的事情是,您是否可以通过显式模板实例化来节省一些空间/时间: 显式模板实例化 - 何时使用? 该答案的“如何快速分析您的构建以查看它是否会从模板实例化中获益”部分还包含一种查找重复项的方法大型 (C++) 项目中跨对象文件的对象。
One good bet would also be to have a look at the possibilities mentioned at Tool to analyze size of ELF sections and symbol e.g.:
I've seen cases where debug symbols are MASSIVE in C++, e.g. 30x larger than the rest of the binary, so this is definitely one of the things to look out for, the above
size
command would tip you off immediately due to huge debug related sections, and you can double check by stripping the binary withstrip
org++ -s
.Another thing to look out for is if you can save some space/time with explicit template instantiation: Explicit template instantiation - when is it used? The "How to quickly analyze your build to see if it would gain a lot from template instantiation" section of that answer also contains a methodology to find duplicate objects across object files in a large (C++) project.
您可以通过添加编译标志
-flto -Wl,-allow-multiple-definition
并且可以添加-fuse-linker-plugin
。-Wa,-mbig-obj
不适用于 x86/32 位架构(仅限 x64)You can by adding the compilation flags
-flto -Wl,-allow-multiple-definition
and you can add-fuse-linker-plugin
.-Wa,-mbig-obj
do not work on x86/32bits architecture (only x64)这是我用来查看编译时值的宏:
然后在编译时高兴地查看哪些符号占用了空间。
编辑:由于似乎没有人理解这一点,我将澄清:使用它的方法是添加compiler_check_number(sizeof(<在此处插入结构或全局变量>))。 编译器会将变量或结构的大小作为编译时错误吐出。 代码很少是造成巨大目标文件的原因。
我一直使用它来查看事物有多大,而无需运行调试器。
Here's a macro I use to see compile time values:
Then go happy at compile time to see what symbols are taking up space.
Edit: Since no one seems to understand this, I'll clarify: the way to use this is to add
compiler_check_number(sizeof(<insert struct or global variable here>))
. The compiler will spit out the size of the variable or struct as a compile time error. Very rarely is code the reason for a huge object file.I use this all the time to see how big things are without having to run a debugger.
当目标文件大于最小大小时,可能有多种原因:
首先,我建议检查您是否正在使用调试信息进行构建,这会导致我的经验中最膨胀。
There can be several reasons when object files are bigger than they have to be at minimum:
At first I suggest to check if you're building with debug information, this causes the most bloat in my experience.