Keil:虚拟或受保护的析构函数和堆

Keil: virtual or protected destructor and heap

本文关键字:析构函数 受保护 虚拟 Keil      更新时间:2023-10-16

我正在使用Keil 4和Cortex M3的ARM工具集(如果这很重要的话)。我尝试了这个简单的代码:

class Base
{
public:
virtual ~Base() {}
};
class Derived : public Base
{
public:
int b;
virtual ~Derived() {}
};

如果我在本地(main内部)创建一个Derived实例,一切都很好:调试正常,程序大小约为300字节。

如果我创建Derived的静态或全局实例,程序大小将增加到1000字节,调试会话将在BKPT指令上停止。

我认为这是因为堆大小被设置为默认值(零)。当我添加一些堆时,调试就开始工作了。

将析构函数设为受保护但非虚拟的会导致相同的行为。将通常的方法虚拟化并没有。

所以,我的问题是:在这种情况下,编译器需要堆的原因是什么?

Vtab是静态创建的(我检查过),全局对象也应该是静态的。当我不需要动态分配时,再浪费700字节用于堆分配代码(以及堆本身的空间)有点愚蠢。

(我将析构函数设为虚拟,以防止出现警告。)

当在函数之外定义实例时,会发生两件事。首先,在调用main之前先调用对象的构造函数。程序员必须小心,构造函数不执行任何可能需要稍后进行初始化的操作。其次,实例的内存是在堆上分配的,因为在main之前没有本地作用域。嵌入式系统程序员在实例化全局对象时必须特别小心。如果构造函数依赖于一些在main之前未初始化的硬件,那么可能会发生不好的事情。熟悉Keil提供的C启动文件(汇编语言模块,在初始化堆后调用main,将flash复制到ram,并调用全局构造函数)。

答案在这里,在Keil论坛上-http://www.keil.com/forum/21859/.原因是生成了从main返回后调用的函数"__aeabi_atexit"。这有点有趣,因为这种返回在嵌入式系统中永远不会发生。