难以追踪内存泄漏

时间:2016-07-29 20:10:50

标签: c++ memory-leaks c++14 valgrind

我是c ++编程的新手,并且在追踪内存泄漏方面遇到了很多困难,你能帮我找到发生这种情况的地方吗? 这就是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)

这是我的插入功能:

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

这些是我的析构函数&amp;明确的功能:

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

1 个答案:

答案 0 :(得分:0)

  

== 9851 ==在0x4C2E0EF:operator new(unsigned long)(在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so中)

     

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

这里告诉你,在第228行的AVLtree.h中你有一个

new unsigned long;

您尚未将任何代码注释为AVLtree.h的第228行,而代码new中的任何内容都不是更复杂的类型(例如{{1} }})。

第二个问题

  

== 9851 == 1个区块中的72,704个字节仍然可以在2个丢失记录中找到

     

== 9851 ==在0x4C2DB8F:malloc(在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so中)

     

== 9851 == by 0x4EC3EFF:??? (在/ 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)

node是动态加载器调用静态/全局对象(https://github.com/lattera/glibc/blob/master/elf/dl-init.c#L121-L133)的构造函数。

因此,这表明您在静态/全局级别泄漏内存。