这种内存泄漏从何而来?

Where does this memory leak come from?

在我的 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;
}

这部分代码在使用时会导致内存泄漏,知道吗,这里可能出了什么问题? 编辑:处理 realloc 为 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 个字节。

你读错了错误:

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. 复制构造函数复制 internal_array 的内容,而不是指针。
  3. 赋值运算符复制内容,而不是指针。考虑复制和交换习语。
  4. 移动构造函数复制指针,但使另一个对象无效。
  5. 移动赋值交换指针,或者分配一个指针并释放另一个。

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

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