内存泄漏从何而来?

时间:2018-11-21 02:02:16

标签: c++ memory memory-leaks dynamic-memory-allocation realloc

在ArrayList的实现中,我有一个调整数组大小的方法。看起来像这样:

template<typename T>
int ArrayList<T>::changeSize(int newsize)
{
    T* tmp = (T*)(T*)realloc(internal_array,sizeof(T)*newsize);
    if(tmp == NULL)
    {
        return 0;
    }
    internal_array=tmp; 
    Capacity = newsize;
    return 1;
}

这部分代码在使用时会导致内存泄漏,任何想法,这可能是什么问题? 编辑:处理重新分配为NULL仍然没有帮助,更新了代码并添加了地址消毒剂输出:

================================================ ================== == 4615 ==错误:LeakSanitizer:检测到内存泄漏

从1个对象分配的16个字节中直接泄漏:

#0 0x7f0c9d1b5f40 in realloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdef40)
#1 0x557b3b693fb2 in ArrayList<int>::changeSize(int) (/media/mdvorak/Maxtor/Vysoká Škola/PA1/progtest5/a.out+0x2fb2)
#2 0x557b3b6939c4 in ArrayList<int>::Add(int) (/media/mdvorak/Maxtor/Vysoká Škola/PA1/progtest5/a.out+0x29c4)
#3 0x557b3b692671 in readInput(ArrayList<int>*) (/media/mdvorak/Maxtor/Vysoká Škola/PA1/progtest5/a.out+0x1671)
#4 0x557b3b693339 in main (/media/mdvorak/Maxtor/Vysoká Škola/PA1/progtest5/a.out+0x2339)
#5 0x7f0c9cd07b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)

1个对象分配的4个字节直接泄漏:

#0 0x7f0c9d1b5f40 in realloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdef40)
#1 0x557b3b693fb2 in ArrayList<int>::changeSize(int) (/media/mdvorak/Maxtor/Vysoká Škola/PA1/progtest5/a.out+0x2fb2)
#2 0x557b3b693e0b in ArrayList<int>::Remove(int) (/media/mdvorak/Maxtor/Vysoká Škola/PA1/progtest5/a.out+0x2e0b)
#3 0x557b3b692d07 in findMinDistances(ArrayList<int>) (/media/mdvorak/Maxtor/Vysoká Škola/PA1/progtest5/a.out+0x1d07)
#4 0x557b3b6934a3 in main (/media/mdvorak/Maxtor/Vysoká Škola/PA1/progtest5/a.out+0x24a3)
#5 0x7f0c9cd07b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)

摘要:AddressSanitizer:2个分配中泄漏了20个字节。

1 个答案:

答案 0 :(得分:1)

您正在读取错误错误:

Direct leak of 16 byte(s) in 1 object(s) allocated from:

#0 0x7f0c9d1b5f40 in realloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdef40)
#1 0x557b3b693fb2 in ArrayList<int>::changeSize(int) (/media/mdvorak/Maxtor/Vysoká Škola/PA1/progtest5/a.out+0x2fb2)
#2 0x557b3b6939c4 in ArrayList<int>::Add(int) (/media/mdvorak/Maxtor/Vysoká Škola/PA1/progtest5/a.out+0x29c4)
#3 0x557b3b692671 in readInput(ArrayList<int>*) (/media/mdvorak/Maxtor/Vysoká Škola/PA1/progtest5/a.out+0x1671)
#4 0x557b3b693339 in main (/media/mdvorak/Maxtor/Vysoká Škola/PA1/progtest5/a.out+0x2339)
#5 0x7f0c9cd07b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)

很明显,在ArrayList<int>::changeSize(int)处分配的内存是泄漏的内存。它没有说什么操作导致它泄漏。

这意味着changeSize(int)没问题。问题出在其他地方。您必须确保遵循5的规则:

  1. 析构函数释放内存。
  2. Copy构造函数复制internal_array的内容,而不是指针。
  3. 赋值运算符复制内容,而不是指针。考虑复制和交换的习惯用法。
  4. 移动构造函数复制指针,但使另一个对象无效。
  5. 移动分配交换指针,或分配一个指针并释放另一个指针。

该错误可能是由于缺少或错误了上述其中一项。一种使编译时更容易捕获此类错误的好方法是使用std::unique_ptr with a custom deleter而不是手动释放。

请注意,您的代码将崩溃和/或泄漏任何复杂的内存,例如T = vector或T = big num。您可以添加static_assert(std::is_trivial<T>::value);来确保它没有用std::map实例化。