2

時間数、現在の時刻、および実際の時刻の 3 つの引数を取る小さなソルバーを作成しています。

プログラム自体は正常に動作しますが、修正できないメモリ リークがあります。

コード:

私のメインの中で:

vector<ClockState> moves = sol.solve(curClock);

solve方法:

std::vector<Game> Solver<Game>::solve(Game curCfg){
    std::vector<Game> result;
    std::vector<Game> seen;
    std::queue<Game> q;

    q.push(curCfg);
    seen.push_back(curCfg);

    std::vector<Game> moves;

    Game cfg = q.front();
    Game * newCfg = NULL;

    while (q.size() > 0) {

        if (q.front().isEndState()) {
            break;
        }

        cfg = q.front();
        q.pop();

        cfg.getMoves(moves);
        for (unsigned int i = 0; i < moves.size(); i++) {
            if (find(seen.begin(), seen.end(), moves[i]) == seen.end()) {
                newCfg = new Game(cfg);
                moves[i].setPrev(newCfg);
                q.push(moves[i]);
                seen.push_back(moves[i]);
            }
        }
    }

    delete newCfg;

    if(q.empty()){
        return result;
    }

    Game temp(q.front());

    while (true) {
        result.push_back(temp);
        if (temp == curCfg) {
            break;
        }
        temp = temp.prev();
    }
    reverse(result.begin(), result.end());
    return result;
}

そして私のsetPrevメソッド(ClockState内)

void ClockState::setPrev(ClockState *prev) {
    previous = prev;
}

previousClockState クラス内のポインターです。

私の理解では、削除する必要があり、削除newCfgしようとしてもメモリリークが発生します。

ここからの出力は次のとおりですvalgrind --leak-check=full ./clock 12 10 3

==16856==
==16856== HEAP SUMMARY:
==16856==     in use at exit: 64 bytes in 4 blocks
==16856==   total heap usage: 28 allocs, 24 frees, 2,095 bytes allocated
==16856==
==16856== 64 (16 direct, 48 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
==16856==    at 0x402569A: operator new(unsigned int) (vg_replace_malloc.c:255)
==16856==    by 0x8049AB1: Solver<ClockState>::solve(ClockState) (Solver.h:102)
==16856==    by 0x804964B: main (clock.cpp:106)
==16856==
==16856== LEAK SUMMARY:
==16856==    definitely lost: 16 bytes in 1 blocks
==16856==    indirectly lost: 48 bytes in 3 blocks
==16856==      possibly lost: 0 bytes in 0 blocks
==16856==    still reachable: 0 bytes in 0 blocks
==16856==         suppressed: 0 bytes in 0 blocks
==16856==
==16856== For counts of detected and suppressed errors, rerun with: -v
==16856== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 17 from 6)

102行目はnewCfg = new Game(cfg);

ソルバーがそのベクトルを返すと、最終的に結果を出力し、その直後に次のように前の各ベクトルを削除します。

for(int j = 0; j < moves.size(); j++){
    moves[j].deletePrev();
}

deletePrev() はただ言うdelete previous;

感謝します。

4

2 に答える 2

4

aloopで新しいオブジェクトを作成しますが、削除するのは1つだけであるため、メモリリークが発生します。

各移動をループして、ポインタによる要素ポインタを削除する必要がありpreviousます

または、オブジェクトを1つだけ作成Gameし、それが終わったら削除します(同じオブジェクトを何度も再作成しているため)。

さらに別の方法は、他の多くのオブジェクト間でオブジェクトを共有したくない場合は、Gameオブジェクトを値でコピーすることです(したがって、必要ないnewか、必要ありません)。delete

別のアプローチは、ある種のスマートポインタを使用することです(たとえば、BOOSTから、またはC ++ 11を使用します)

于 2012-05-17T17:18:24.973 に答える
2

このコード:

Game * newCfg = NULL;
while (q.size() > 0) {

    if (q.front().isEndState()) {
        break;
    }

    cfg = q.front();
    q.pop();
    std::vector<Game> moves;
    cfg.getMoves(moves);
    for (int i = 0; i < moves.size(); i++) {
        if (find(seen.begin(), seen.end(), moves[i]) == seen.end()) {
            newCfg = new Game(cfg);
            moves[i].setPrev(newCfg);
            q.push(moves[i]);
            seen.push_back(moves[i]);
        }
    }
}

delete newCfg;

ゲームへのポインタであるnewCfgという名前の変数を宣言します。ただし、ループとは別に、Gameクラスの新しいインスタンスを作成し続け、それらをmovesコンテナに追加します。移動コンテナに追加したGame*の各インスタンスを「削除」する必要があります。

上記のコードは、基本的にこのコードと同じことを行います。

int* myInts = NULL;
myInts = new Int[2];
myInts = new Int[5];
delete myInts; // <-- only deletes memory for Int[5],
               // Int[2] memory is dangling in no-mans-land
于 2012-05-17T17:19:49.300 に答える