2017-02-18 34 views
-1

Чувствую, что я бичу головой о кирпичную стену здесь.Утечка памяти в моей программе; деструктор не вызван?

Я не уверен, что деструктор фактически вызван. Я использую priority_queue для хранения множества узлов. Каждый узел имеет член m_grid, представляющий собой 2D массив структур. Эта сетка представляет собой единственные указатели, которые я явно использую в своей программе.

По какой-то причине я получаю много утечек. Не могли бы вы мне помочь?

Вот деструктор:

grid::~grid() 
{ 
    for (int i = 0; i < m_width; i++) 
    { 
    delete[] m_grid[i]; 
    m_grid[i] = NULL; 
    } 

    delete[] m_grid; 
    m_grid = NULL; 
} 

Оператор присваивания:

grid& grid::operator=(const grid& g) 
{ 
    m_x_rad = g.m_x_rad; 
    m_y_rad = g.m_y_rad; 
    m_width = g.m_width; 
    m_height = g.m_height; 
    m_orientation = g.m_orientation; 

    if (m_width != 0) 
    m_grid = new cell* [m_width]; 

    // from left to right 
    for (int i = 0; i < m_width; i++) 
    { 
    m_grid[i] = new cell [m_height]; 

    // from top to bottom 
    for (int j = 0; j < m_height; j++) 
    { 
     m_grid[i][j].m_occupied = g.m_grid[i][j].m_occupied; 
     m_grid[i][j].m_rad = g.m_grid[i][j].m_rad; 
    } 
    } 

    return *this; 
} 

Оператор присваивания похож и, как ожидалось. Наконец, вот немного выхода VALGRIND (там много, но все это касается сетки :: SetSize() или сетки :: оператор =.

==13329== 200 (40 direct, 160 indirect) bytes in 1 blocks are definitely lost in loss record 25 of 166 
==13329== at 0x4C2E80F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==13329== by 0x4020C1: grid::operator=(grid const&) (grid.cpp:192) 
==13329== by 0x40A02E: node::operator=(node const&) (node.cpp:129) 
==13329== by 0x4075A6: __push_heap<__gnu_cxx::__normal_iterator<node*, std::vector<node> >, long int, node, __gnu_cxx::__ops::_Iter_comp_val<std::greater<node> > > (stl_heap.h:135) 
==13329== by 0x4075A6: push_heap<__gnu_cxx::__normal_iterator<node*, std::vector<node> >, std::greater<node> > (stl_heap.h:199) 
==13329== by 0x4075A6: push (stl_queue.h:502) 
==13329== by 0x4075A6: aStarGraphSearch(basic_map const&, node&, std::unordered_map<int, basic_node, std::hash<int>, std::equal_to<int>, std::allocator<std::pair<int const, basic_node> > >&, std::priority_queue<node, std::vector<node, std::allocator<node> >, std::greater<node> >&) (main_functions.cpp:216) 
==13329== by 0x4088ED: search(int) (main_functions.cpp:706) 
==13329== by 0x401AAA: main (main.cpp:13) 

Я действительно борется здесь. У меня не было эти вопросы, когда я был с использованием стеки вместо приоритетной очереди. Любая помощь приветствуется.

+2

Без [mcve] нет авторитетного ответа, но очень очевидно, что конструктор копирования не может уничтожить существующие динамически распределенные члены класса, следовательно, утечка памяти. –

+1

'operator =' выделяет память без удаления старой памяти. Это намеренно? –

+0

Если вам разрешено, используйте 'std :: vector >' вместо 'cell **' для захвата сетки. –

ответ

1

Вы не удаляют m_grid (и массивы он содержит) в вашем операторе присваивания.

+0

Если я удалю 'm_grid', я больше не смогу получить доступ к сетке позже ... правильно? – hockeysaint

+0

@hockeysaint Это верно. Однако, если вы не удалите его, у вас будет утечка памяти. – emlai

+0

О, я неправильно понял. Исправьте меня, если я ошибаюсь, но теперь я понимаю, что указывать «m_grid» в «новой ячейке» 'оставляет за собой все, что указывал« m_grid ». Я думал, вы имели в виду, что я должен удалить вновь созданный 'm_grid'. – hockeysaint

0

вызова в оператор присваивания Безразлично 't автоматически вызывать деструктор в первую очередь. Вы должны очистить любую память, уже принадлежащую объекту, самостоятельно, если вы собираетесь повторно поместите его с новой памятью.

Уступка не создает новый объект; он просто изменяет объект, который у вас уже есть.

+0

Конечно, но что-то вроде 'node top_node = frontier.top();' (где граница - моя очередь) должна сделать 'top_node' точной копией' frontier.top() ', как я ее понимаю. – hockeysaint

+0

@hockeysaint: Это не вызывает оператор присваивания. Это инициализация, а не задание. –