2

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

class Base
{
    public:
    virtual ~Base() {}
};

class Derived : public Base
{

    public:
    int b;

    virtual ~Derived() {}
};

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

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

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

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

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

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

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

4

2 回答 2

1

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

于 2013-07-03T12:48:02.597 回答
1

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

于 2013-07-01T16:34:11.020 回答