2

std :: listとメモリリークに問題があります:

class AbstractObject
{
    public:
        virtual void Say() = 0;
}
class RealObject : public AbstractObject
{
    public:
        virtual void Say() { cout << "Real Obj Says..." << endl; } //Do I need the "virtual" keyword here too?
}
class AnotherRealObject : public AbstractObject
{
    public:
        virtual void Say() { cout << "Another Real Obj Says..." << endl; } //Do I need the "virtual" keyword here too?
}
class PackOfObjects
{
    public:
        std::list<AbstractObject*> objects; //list of pointers because it doesn't let me create a list of an abstract class
        void Say()
        {
            for(std::list<AbstractObject*>::iterator obj = objects.begin(); obj != objects.end(); obj++)
            {
                (*obj)->Say();
            }
        }
}
int _tmain(int argc, _TCHAR* argv[])
{
    PackOfObjs myObjs;

    RealObject objA;
    myObjs.objects.push_back(&objA); //This adds 1 memory leak
    AnotherRealObject objB;
    myObjs.objects.push_back(&objB); //This adds another 1 memory leak

    _gettch();
    _CrtDumpMemoryLeaks();
    return 0;
}

PackOfObjsが宣言されただけで、すでに2つのメモリリークがあり、std :: listを削除するとそれらはなくなり、リストに追加するアドレスごとに1ずつ増加します。リストをクリアして、クリアする前にポイントされたすべてのオブジェクトを削除するいくつかのコードを試しましたが、少なくとも2つのメモリリークがまだ残っています。

新しいものを使用しなかったので(追加した要素でも)、リスト自体がいくつかの変数を作成し、それらを削除しないと推測していますが、これを修正するにはどうすればよいですか?

4

3 に答える 3

5

実行する_CrtDumpMemoryLeaks()と、内部に割り当てられたすべてのオブジェクトがmainまだ存在します。あなたは_CrtDumpMemoryLeaks()早すぎます。代わりに、これを試してください:

int _tmain(int argc, _TCHAR* argv[])
{
    {
        PackOfObjs myObjs;

        RealObject objA;
        myObjs.objects.push_back(&objA); //This adds 1 memory leak
        AnotherRealObject objB;
        myObjs.objects.push_back(&objB); //This adds another 1 memory leak

        // <- all memory used by the list is freed here
    }
    _gettch();
    _CrtDumpMemoryLeaks();
    return 0;
}

_CrtDumpMemoryLeaks推奨される呼び出し方法は、グローバルオブジェクトのデストラクタであることを覚えているようです。それは他のグローバルオブジェクトにはまだ時期尚早かもしれませんが、少なくともその場合、内部で作成されたすべてのオブジェクトはmainすでに破棄されています。

struct memory_leak_dumper
{
    ~memory_leak_dumper(){ _CrtDumpMemoryLeaks(); }
};
memory_leak_dumper _dumper; // this is a global object
于 2012-12-28T23:55:24.620 に答える
1

メモリリークをチェックするには、次を使用する必要があります。

_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

あなたのメインの初めに

リークはプログラムの終了時にチェックされます。オブジェクトがまだスタック上にあるときにリークをチェックするため、リークは発生しません。

仮想メソッドを使用する場合は、仮想デストラクタを追加する必要があります。ただし、メモリリークは発生しませんが、リストに動的に割り当てられたオブジェクトが含まれる場合は、AbstractObjectの仮想デストラクタが必須になります。

あなたの質問について:

「//ここにも「virtual」キーワードが必要ですか?」

はい、リスト<>が基本クラスのポインタ型である限り

于 2012-12-29T00:00:17.180 に答える
0

K-balloの答えを拡張するため_CrtDumpMemoryLeaksに、ヒープ上のオブジェクトを技術的に検査します。ヒープに直接何も割り当てませんでしたが、std::list(およびその点でメモリを動的に管理するすべてのコンテナ)は割り当てます。そうでない場合、動的サイズはオプションになりません。

つまり、技術的にはリークはありませんが、呼び出した時点では_CrtDumpMemoryLeaks、動的に割り当てられたメモリは(まだ)解放されずに使用されています。

std::listを別のスコープで囲むか、提案されているようにグローバルオブジェクトのデストラクタを{ ... }呼び出すと、リークが発生しないはずです。_CrtDumpMemoryLeaks

于 2012-12-29T00:01:31.040 に答える