【问题标题】:Keil: virtual or protected destructor and heapKeil:虚拟或受保护的析构函数和堆
【发布时间】:2012-11-06 20:44:18
【问题描述】:

我正在将 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 个字节用于堆分配代码(以及堆本身的空间)有点愚蠢。

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

【问题讨论】:

    标签: c++ keil virtual-destructor


    【解决方案1】:

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

    【讨论】:

    • 其实,keil 支持已经在这里回复了我keil.com/forum/21859。基本上,你在写——keil,出于某种原因,会生成代码来记录销毁顺序。退出主程序后将调用此代码。但是你所说的在堆上创建全局对象是不正确的。全局对象在静态内存中创建,不使用任何堆。
    • 请求船长的原谅,但是静态内存在堆上(而不是在栈上)。
    • Bruce,其实静态内存是第三个内存块,既不是栈也不是堆。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2020-03-06
      • 2016-01-22
      • 2012-11-23
      • 2013-11-03
      • 2023-03-23
      • 2012-02-16
      • 2011-06-01
      • 1970-01-01
      • 2017-09-03
      相关资源
      最近更新 更多