Declaring abstract class (pure virtual method) increase binary size substantially(声明抽象类(纯虚方法)大幅增加二进制大小)
问题描述
故事如下:我正在使用 AC6 Toolpack 在 Linux 中为 ARM Cortex-M0 处理器开发 C++ 软件.在我使用 Keil(在 Windows 中)(拥有自己的工具链)之前,我已经迁移到 GNU-toolchain ((GNU Tools for ARM Embedded Processors) 5.2.1) .我意识到的第一件事是;二进制文件大小大幅增加.我已经测试了每个编译器优化(除了链接时间优化,它在内联汇编中给出错误,不是问题的一部分,但可能与答案有关).然后开始检查可执行文件(elf文件不是bin,gnu 使用任何可用的工具生成两者):objdump、readelf、nm.我发现一些导致大小增加的符号,重要的是:'d_print_comp_inner
'、'd_exprlist
'、'd_template_args
'.但不知道是什么导致这些函数以二进制形式出现.(我使用了最少的库:nano newlib).长话短说,我开始一一消除代码以找到罪魁祸首.终于是抽象方法声明了!
Here is the story:
I am developing C++ software for ARM Cortex-M0 processor in Linux with AC6 Toolpack. Before I was using Keil (in windows) (who has their own toolchain) and I have migrated to GNU-toolchain ((GNU Tools for ARM Embedded Processors) 5.2.1) . First thing i have realized is; binary file size increased substantially. I have tested every compiler optimizations (except link time optimization, it gives an error in inline assembly, not part of question but may be related to answer). Then started to inspect executables (elf file not bin, gnu produces both) with any tool available :objdump, readelf, nm. I found some symbols causing size increase, significant ones are: 'd_print_comp_inner
' , 'd_exprlist
', 'd_template_args
'. But have no idea what is causing these functions to appear in binary. (i have used minimal libraries: nano newlib). Long story short I started to eliminate codes one by one to find culprit. At last it was Abstract Method declaration!
定义函数为
而不是
添加 45 KB 和我提到的符号.这是源代码中唯一的变化.基类中存在空定义.请注意:方法仍然是虚拟的,并且在子类中被覆盖
adding 45 KB and the symbols I have mentioned. And this is the only change in source code. Empty definition in base class is present. Note that: method is still virtual and overridden in child classes
没有抽象类的大小输出:
Size output without Abstract Class:
抽象类的大小输出:
这里是抽象方法时出现的符号及其大小,消除了两个版本中出现的符号.(使用nm
工具.不完整列表,大小>=0x60)
Here the symbols and theirs size that shows up when method is abstract, eliminated the ones show up in both versions. (nm
tool is used. Not complete list, the ones with size >=0x60)
一些我熟悉的名字(例如 printf、flush、malloc、fputs 等)甚至在源代码中都没有提到.
Some names familiar to me (such as printf,flush,malloc,fputs etc.) are not even mentioned in the source code.
任何知道导致这种行为的原因的人吗?
Any one with any idea what is causing this behavior?
更新:我已经用标志 --noexception
禁用了异常,所以我没有考虑它.事实证明,在这里提到这个很好地回答了这个问题.
Update:
I was already disabling exceptions with flag --noexception
, so I haven't given any though to it. As it turns out, it is related to answer so good to mention this here.
更新 2:这是最全面的网站如果您跟踪答案中的链接,请解释这一切.
Update 2: This is the most comprehensive website explaining it all, if you track the links in answers.
推荐答案
几乎可以肯定是因为意外包含了异常处理,libc++ 已经内置在其中,无论您是否使用 编译代码--noexception
或任何适当的 gnu 主义.
It's almost certainly because of unexpected inclusion of exception handling, which libc++ has built into it, regardless of whether or not you compile your code with --noexception
or whatever the proper gnu-ism is.
有问题的异常可能是纯虚函数调用"或类似的东西(一个相当模糊的运行时错误,但如果您在基类构造函数中调用虚函数,则可能).
The exception in question is probably 'pure virtual function call' or something like that (a fairly obscure runtime error to get, but possible if you call virtual functions in the base class constructor).
答案是提供您自己的空实现,atexit(),以及您并不真正需要的任何随机标注.一旦你这样做了,链接器就不会拖入其他东西(它会拖入其他东西,它会拖入其他东西,等等).
The answer is to provide your own empty implementation of this, atexit(), and whatever random callout that you don't really need. Once you do that, the linker won't drag in the other stuff (which drags in other stuff, which drags in other stuff, etc).
这是我在我们项目中所拥有的,尽管您的 libc++ 版本可能有所改变
Is what I have on our project, though things may have changed in your version of libc++
这篇关于声明抽象类(纯虚方法)大幅增加二进制大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!