【问题标题】:G++ makes smaller binary than GCC after C++ compatibility changes, but slightly larger than the prior binary?在 C++ 兼容性更改后,G++ 生成的二进制文件比 GCC 更小,但比之前的二进制文件略大?
【发布时间】:2012-12-04 20:21:11
【问题描述】:

我对 C 代码库进行了一些更改,以便它可以在 G++ 下编译。似乎正在工作,但有一些烦恼和-fpermissive -fshort-wchar 的黑客攻击。

出于好奇,我比较了修改前 GCC 构建的可执行文件的剥离 -O2 大小和修改后 G++ 构建的可执行文件的大小。 “之后”大了 32 个字节(在 500K 的二进制文件上)。我很惊喜它是如此接近,但我很想知道为什么如果优化器是那个一致的,它不会是 100% 一致的?但也许是添加 overload for strchr 引起的。

对我来说还不够重要,不用担心。但后来我决定使用 GCC 进行 C 构建,同时考虑到我的 C++ 兼容性更改。剥离的 -O2 可执行文件比我更改之前的 C 版本大 4096 字节

有没有人知道为什么这三个尺寸会以这种方式发生,以及为什么会是这样一个“整数”? C++ 的变化基本上是所有应该优化的东西,无论是在 C 还是 C++ 中。基本上:

  • 引入了不透明类型,以便以前在接口中定义为采用 void* 的函数将一致地命名-mangle。通过 opaque 类型的宏将一些强制转换分配给本地人到适当内部类型的本地人

  • 消除一些老式 C 函数头定义的实例

  • 为一些以前没有指定链接的全局常量修改“extern”链接,暂时容忍keeping the assignments in the headers,但希望反对

  • 将一些有符号字符更改为无符号字符,将一些无符号长整数更改为无符号整数(但绝不反之)

如果有人对这个优化案例有很好的直觉,那么它会节省我单独退出每组相关更改以查看它们如何影响大小的时间......!

【问题讨论】:

  • 所有这些尺寸差异是如此之小,我会完全忽略它们。他们极不可能提出任何有趣、破碎或相关的建议。甚至可能只是链接器顺序导致不同数量的填充。
  • 一个ELF可执行文件里面有很多东西,其中一些被四舍五入到给定2的幂的倍数。可能这就是4096的原因。你应该检查objdump -x <exe-file>的输出在这两个程序上并逐位比较。
  • @DavidSchwartz 在大多数情况下我会同意,并且想忽略它们,但我正试图将一些更改整合到一个非常注重大小且不一定对鞠躬友好的 C 项目中为那些对使用 C++ 编译器构建感兴趣的人服务的修改。所以至少有答案是好的。如果它是 ELF 块大小并且可以在噪音中解释,那么能够证明这将很方便......
  • @rodrigo 感谢您的提示,我会调查一下...
  • 对罗德里戈的评论稍作修正。 ELF 可以组织成块来改进代码页的交换。 4096 是常见的块大小。整个可执行文件不需要 2 的幂。是否使用这种策略完全取决于编译器。这可能意味着,如果增加 32 字节的大小超出了块边界,则您需要为整个块付费。

标签: c++ c g++ compiler-optimization


【解决方案1】:

记住:C++ 程序本质上并不比 C 程序大。编译可能需要更多时间,但没有什么东西可以让 C++ 程序变得更大。

实际上...由于为undefined behavior 留下了更严格的形式和回旋空间,C++ 编译器可能能够比 C 编译器对 C 代码库进行更多优化。

(又名我) 所描述的差异很小。正如@rodrigo 和@MelNicholson 指出的那样,即使是微小的差异也可能会因块大小的舍入而被夸大。因此,单个字节的实际差异可能导致 4096 字节的文件大小差异。

获取一堆 C 编译器的回归测试,将其构建为 C 与 C++ 并查看可执行文件大小是否有任何显着差异,然后寻找导致这些差异的模式,这可能会很有趣。如果你(又名我)有时间。它可能会提供数据以反馈到编译器可以改进的地方。但在 500K 的可执行文件上,这种大小的单实例差异基本上没有什么可学习的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-04
    • 2016-01-13
    相关资源
    最近更新 更多