我用最新的arm-none-eabi-gcc 6.3在手臂皮质m3上使用c ++进行愚弄。 我创建了一个虚拟类并创建了该类的全局对象:
class B
{};
class A : B
{
public:
A()
{
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;
GPIOC->CRH = 1;
GPIOC->ODR |= 1<<8;
}
virtual void foo()
{}
virtual ~A()
{}
};
A a;
int main(void) { while(1); }
此代码编译为1620个字节。如果我删除虚拟dtor,它编译为1304字节。这是一个显而易见的差异。
我去查看了assembly和.map文件,看到如果我使用虚拟dtor,许多不同的运行时函数都链接到我的二进制文件。有malloc和free和_static_initialization_and_destruction等等。
奇怪的是:我不明白他们是怎么称呼的? Main叫做这样:
8000260: d3f9 bcc.n 8000256 <FillZerobss>
8000262: f000 f89f bl 80003a4 <SystemInit>
8000266: f000 f957 bl 8000518 <__libc_init_array>
800026a: f000 f865 bl 8000338 <main>
800026e: 4770 bx lr
从main返回后(顺便说一句,从不发生)执行只是坐在bx lr上,它一直跳到同一个地址。
因此,我无法看到要调用静态对象取消初始化的路径。为什么它不能作为无法访问的代码进行优化?
我这样编译:
arm-none-eabi-g++ -c -fmessage-length=0 -mcpu=cortex-m3 -mthumb -fdata-sections -ffunction-sections -fno-rtti -fno-exceptions -fno-threadsafe-statics
和arm-none-eabi-g++ -mcpu=cortex-m3 -mthumb --specs=nosys.specs --specs=nano.specs -Wl,--gc-sections -T "${ProjDirPath}/src/Startup/STM32F100XB_FLASH.ld" -ffreestanding
我尝试添加-fno-use-cxa-atexit或制作一个虚拟__cxa_atexit
- 它确实使二进制稍微更小(这甚至比没有效果更奇怪)。
有没有办法完全禁用静态对象的破坏?
更新:
答案 0 :(得分:0)
如果没有整个程序优化,则不清楚析构函数是否实际无法访问。可能有另一个带有构造函数的翻译单元,该构造函数生成一个稍后调用exit
函数的线程。