2

我正在创建一个需要三个参数的小型求解器:小时数、当前时间和真实时间。

该程序本身运行良好,但存在我无法修复的内存泄漏。

代码:

在我的主要内容中:

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;
}

previous是 ClockState 类中的一个指针。

据我了解,我需要删除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);

当 Solver 返回该向量时,我最终打印结果,然后直接删除每个先前的内容,如下所示:

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

deletePrev() 只是说delete previous;

欣赏它。

4

2 回答 2

4

您在循环中创建新对象,但只删除一个,这会导致内存泄漏。

您需要遍历每个移动并删除指针指向的元素previous指针

或者,只创建一个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 的指针。但是,在循环之外,您需要保留 Game 类的新实例并将它们添加到移动容器中。您需要“删除”您添加到移动容器中的每个 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 回答