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++ では、コンストラクターは階層の上方向に呼び出されます。つまり、 を作成するDerivedと、Base()が の前に実行されDerived()ます。これは、2 回実行していobjPtr = new SomeObject;て、1 回だけ削除していることを意味します。

また、特にptrDerivedからインスタンスを削除する場合は、基本クラスのデストラクタを仮想化する必要があります。Base

于 2013-03-22T01:21:34.383 に答える
3

基本クラスのデストラクタを仮想化する必要があります。

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

Sub :: Sub()コンストラクターは、Base :: Base()スーパーコンストラクターによって最初のSomeObjectが割り当てられた後、2番目の追加のSomeObjectを割り当て、2番目に割り当てられたポインターがobjPtrに割り当てられてリークを引き起こします。

注:Base :: Base()は、Sub :: Sub()によって暗黙的に呼び出されます

解決策:Sub :: Sub()で不要な割り当てを削除するだけです

別の提案:継承で推奨されているように、ベースデストラクタを仮想化する

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、で2回呼び出しBase、次にで2回呼び出すことになりSubます。その後、割り当てられたメモリBaseが失われ、リークが発生します。virtualまた、派生クラスで正しく機能するようにデストラクタを作成する必要があります。

于 2013-03-22T01:20:39.877 に答える
0

そのポインタのメモリは 2 回割り当てられます。したがって、新しいメモリをすべて解放することは決してありません。ポインターをプライベート メンバーにして、基本クラスにのみ割り当てるだけです。

于 2013-03-22T01:35:39.427 に答える