2012-05-17 5 views
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;

Цените его.

+3

Лучше использовать смарт-указатель (например, shared_ptr), поэтому вам не нужно заботиться о сопряжении новые и удалять. – kennytm

ответ

4

Вы создаете новые объекты в aloop, но удаляете только одно, что приводит к утечке памяти.

Вы должны перебрать каждый ход и удалить указатель элемента, на которую previous указатель

Или просто создать только один Game объект и удалить его, когда вы сделали с ним (как вы воссоздающий идентичны объекты во много раз)

Еще одна альтернатива для копирования Game объекта по значению (поэтому не new или delete не требуется), если вы не хотите, чтобы разделить объект среди многих других объектов

Еще в pproach - использовать какой-то умный указатель (например, от BOOST или использовать C++ 11)

+0

Вы предлагаете удалить newCfg до завершения цикла while или после завершения цикла for? –

+0

'newCfg' имеет только последний объект, который вы создали, вам нужно пройти все остальные. Что касается того, когда нужно удалить: когда вам больше не нужен объект (поэтому после этого код не будет пытаться получить доступ к удаленному объекту после этого) – Attila

+0

Ну, после того, как решатель завершает итерацию, он возвращает ходы, которые затем перебираю, чтобы распечатать каждый шаг. Предлагая после того, как я распечатаю каждый шаг, я перебираю результаты и удаляю предыдущее? –

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 *, который вы добавили в контейнер перемещений.

ваш код выше, по существу делает то же самое, как этот код:

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 
+0

Спасибо за комментарий. После того, как я распечатаю результаты моего решателя, я теперь удаляю каждый предыдущий для каждой игры внутри ходов. После этого, однако, у меня все еще есть утечка в классе Solver.h. –

+0

Это в другом месте? –

+0

Утечка по-прежнему происходит в 'newCfg = new Game (cfg);' –

Смежные вопросы