5

我在我的代码中使用动态内存分配,并且在尝试删除指向子类的指针时遇到问题。我发现原来分配的内存在使用delete关键字的时候并没有被释放。该功能适用​​于原始基类。

这是一个问题,因为我在 arduino 上运行代码并且 RAM 很快被吃光然后崩溃。

这是一些示例代码:

class Base
{
public:
    Base(){
        objPtr = new SomeObject;
    }
    ~Base(){
        delete objPtr;
    }
    SomeObject* objPtr;
};

class Sub : public Base
{
public:
    Sub(){
        objPtr = new SomeObject;
    }
};



// this works fine
int main()
{
    for (int n=0;n<100;n++) // or any arbitrary number
    {
        Base* basePtr = new Base;
        delete basePtr;
    }
    return 0;
}

// this crashes the arduino (runs out of RAM)
int main()
{
    for (int n=0;n<100;n++) // or any arbitrary number
    {
        Sub* subPtr = new Sub;
        delete subPtr;
    }
    return 0;
}

我想这与基类中析构函数的语法有关。即使我为子类创建了一个自定义析构函数,也会出现同样的问题。

有任何想法吗?

4

5 回答 5

6

在 C++ 中,构造函数在层次结构中向上调用,即在创建时DerivedBase()在执行之前Derived()。这意味着您运行objPtr = new SomeObject;了两次,并且只删除了一次。

你也应该让你的基类析构函数是虚拟的,尤其是当你要从一个ptr中删除Derived实例的时候。Base

于 2013-03-22T01:21:34.383 回答
3

您应该将基类的析构函数设为虚拟。

virtual ~Base(){
    delete objPtr;
}
于 2013-03-22T01:17:59.917 回答
1

Sub::Sub() 构造函数在 Base::Base() 超级构造函数分配第一个对象之后分配第二个额外的 SomeObject ,并且第二个分配的指针分配给 objPtr 引发泄漏。

注意: Base::Base() 被 Sub::Sub() 隐式调用

解决方案:只需删除 Sub::Sub() 中不必要的分配

另一个建议:按照继承的建议使您的 Base 析构函数虚拟化

virtual ~Base(){
    delete objPtr;
}
于 2013-03-22T01:31:37.877 回答
0

当您创建派生类时,它首先调用Base类构造函数,然后调用Subs 构造函数,您可以在此处看到:

class Base
{
public:
    Base(){
       std::cout << "Base() ctor" <<std::endl ;
        objPtr = new int;
    }
    ~Base(){
        delete objPtr;
    }
    int* objPtr;
};

class Sub : public Base
{
public:
    Sub(){
       std::cout << "Sub() ctor" <<std::endl ;
    objPtr = new int;
    }
};

因此,您最终在 . 中调用new了两次Base,然后在Sub. 然后分配的内存Base会丢失,并且您有泄漏。您还需要制作析构函数virtual以使其与派生类一起正常工作。

于 2013-03-22T01:20:39.877 回答
0

该指针的内存被分配了两次。所以你永远不会为它释放所有新的内存。只需将指针设为私有成员并仅在基类中分配它。

于 2013-03-22T01:35:39.427 回答