2016-07-29 2 views
0

Я новичок в программировании на С ++, и у меня много трудностей, прослеживающих утечку памяти. Можете ли вы помочь мне найти, где это происходит? Это то, что Valgrind говорит:Трудно отслеживать утечку памяти

> ==9851== Memcheck, a memory error detector 
==9851== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. 
==9851== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info 
==9851== Command: ./lab6 in81.txt out.txt 
==9851== 
==9851== 
==9851== HEAP SUMMARY: 
==9851==  in use at exit: 72,760 bytes in 2 blocks 
==9851== total heap usage: 198 allocs, 196 frees, 130,465 bytes allocated 
==9851== 
==9851== 56 bytes in 1 blocks are definitely lost in loss record 1 of 2 
==9851== at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==9851== by 0x4025EF: AVLTREE<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::insert(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, AVLTREE<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::node*&) (AVLtree.h:228) 
==9851== by 0x402666: AVLTREE<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::insert(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, AVLTREE<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::node*&) (AVLtree.h:234) 
==9851== by 0x4026AA: AVLTREE<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::insert(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, AVLTREE<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::node*&) (AVLtree.h:239) 
==9851== by 0x402666: AVLTREE<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::insert(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, AVLTREE<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::node*&) (AVLtree.h:234) 
==9851== by 0x401F74: AVLTREE<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::insert(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&) (AVLtree.h:297) 
==9851== by 0x4016FE: interpretLine(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, AVLTREE<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >&) (Main.cpp:20) 
==9851== by 0x401BF3: loadFile(char*, std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >&) (Main.cpp:68) 
==9851== by 0x401E6A: main (Main.cpp:91) 
==9851== 
==9851== 72,704 bytes in 1 blocks are still reachable in loss record 2 of 2 
==9851== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==9851== by 0x4EC3EFF: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21) 
==9851== by 0x40104E9: call_init.part.0 (dl-init.c:72) 
==9851== by 0x40105FA: call_init (dl-init.c:30) 
==9851== by 0x40105FA: _dl_init (dl-init.c:120) 
==9851== by 0x4000CF9: ??? (in /lib/x86_64-linux-gnu/ld-2.23.so) 
==9851== by 0x2: ??? 
==9851== by 0xFFF000626: ??? 
==9851== by 0xFFF00062D: ??? 
==9851== by 0xFFF000636: ??? 
==9851== 
==9851== LEAK SUMMARY: 
==9851== definitely lost: 56 bytes in 1 blocks 
==9851== indirectly lost: 0 bytes in 0 blocks 
==9851==  possibly lost: 0 bytes in 0 blocks 
==9851== still reachable: 72,704 bytes in 1 blocks 
==9851==   suppressed: 0 bytes in 0 blocks 
==9851== 
==9851== For counts of detected and suppressed errors, rerun with: -v 
==9851== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) 

Это мой Insert Function:

int insert(someType& someData, node*& currentSpot) 
{ 
    int i = 0; //i is nodes height. 
    bool isRight = false; 
    if (currentSpot == NULL) 
    { 
     currentSpot = new node(someData); 
     size++; 
     return 1; 
    } 
    if (someData < currentSpot->data) 
    { 
     i = insert(someData, currentSpot->kids[0]); 
     isRight = false; 
    } 
    else if (someData > currentSpot->data) 
    { 
     i = insert(someData, currentSpot->kids[1]); 
     isRight = true; 
    } 
    //rebalancing the tree; 
    rebalance(currentSpot, isRight); 
    //adjusting the height of the tree after rebalancing it. 
    currentSpot->adjustHeight(); 
    return ++i; 

} 

Это то, что моя функция удалить выглядит следующим образом:

bool remove(someType& d, node*& n) 
{ 
    //not passing by reference, in order to use recursion as a stack 
    if (n == nullptr) return false; 
    bool found; 
    if (d > n->data) 
    { 
     found = remove(d, n->kids[1]); 
    } 
    else if (d < n->data) 
    { 
     found = remove(d, n->kids[0]); 
    } 
    else if (d == n->data) 
    { 
     //use ctr 
     // take min value from 
     if (n->kids[1] != nullptr) 
     { 
      // case 1 
      // 2 
      // \ 
      // 3 
      // ... 
      someType minimumValue; 
      minValue(n->kids[1], minimumValue); 
      n->data = minimumValue; 
      rebalance(n, n->tallerChild()); 
      n->adjustHeight(); 
     } 
     else if (n->kids[0] != nullptr) 
     { 
      //case 2 
      // 5 
      ///
      // 4 
      // ...... 
      node* temp = n; 
      n = n->kids[0]; 
      n->adjustHeight(); 
      size--; 
      delete temp; 
     } 
     else 
     { 
      if (n == root) root = nullptr; 
      node* temp = n; 
      n = nullptr; 
      size--; 
      delete temp; 
     } 
     //found and eliminated, tree integrity has been preserved. 
     return true; 
    } 
    //after recursively going down to n, going back up the stack adjusting the height 
    rebalance(n, n->tallerChild()); 
    n->adjustHeight(); 
    return found; 
} 

Это мой деструктор & ясно функция :

void clear() 
{ 
    if (root == nullptr) return; 
    root->clear(); 
    delete root; 
    root = nullptr; 
    size = 0; 
} 
~AVLTREE() 
{ 
     clear(); 
} 

Это мои узлы ясно функции:

void clear() 
     { 
      if (kids[0] != nullptr) 
      { 
       kids[0]->clear(); 
       delete kids[0]; 
      } 
      if (kids[1] != nullptr) 
      { 
       kids[1]->clear(); 
       delete kids[1]; 
      } 
     } 
+0

'node * & currentSpot'? Это не похоже на правильный параметр. – DeepCoder

+2

1. Используйте std :: unique_ptr, чтобы указать право собственности (узлов). 2. Избавьтесь от любых «ясных» функций и переместите эту функцию на деструкторы. 3. Почему бы просто не использовать std :: map, он есть, а кто-то еще уже отлаживал его для вас. –

+0

Можете ли вы показать код rebalance()? – Christophe

ответ

0

== 9851 == в 0x4C2E0EF: оператор новой (без знака длинный) (в /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

== 9851 == by 0x4025EF: AVLTREE, std :: allocator>> :: insert (std :: __ cxx11 :: basic_string, std :: allocator> &, AVLTREE, std :: allocator>> :: node * &) (AVLtree.h: 228)

Вот это говорит о том, что в AVLtree.h на линии 228 у вас есть

new unsigned long; 

Вы не аннотированный какой-либо из вашего кода будет линия 228 AVLtree.h, и ничто в вашем коде new сек ничего, что не более сложный тип (например, node).

Второй выпуск

== 9851 == 72,704 байт в 1 блоках все еще достижим в потере записи 2 из 2

== 9851 == в 0x4C2DB8F: таНос (в/USR/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

== 9851 == by 0x4EC3EFF: ??? (В /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)

== 9851 == по 0x40104E9: call_init.part.0 (DL-init.c: 72)

== 9851 == от 0x40105FA: call_init (DL-init.c: 30)

== 9851 == от 0x40105FA: _dl_init (DL-init.c: 120)

_dl_init является динамический загрузчик, вызывающий конструкторы для статических/глобальных объектов (https://github.com/lattera/glibc/blob/master/elf/dl-init.c#L121-L133).

Таким образом, это указывает на то, что у вас есть что-то на уровне статического/глобального уровня утечки памяти.