这种内存泄漏从何而来?
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 的规则:
- 析构函数释放内存。
- 复制构造函数复制
internal_array
的内容,而不是指针。
- 赋值运算符复制内容,而不是指针。考虑复制和交换习语。
- 移动构造函数复制指针,但使另一个对象无效。
- 移动赋值交换指针,或者分配一个指针并释放另一个。
该错误可能是由于缺少或错误了上述其中一项。在编译期间更容易捕获此类错误的一个好方法是使用 std::unique_ptr with a custom deleter 而不是手动释放。
请注意,如果使用任何复杂的代码,例如 T=vector 或 T=big num,您的代码将崩溃 and/or 内存泄漏。您可以添加 static_assert(std::is_trivial<T>::value);
以确保它不会被实例化,例如 std::map
.
在我的 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 的规则:
- 析构函数释放内存。
- 复制构造函数复制
internal_array
的内容,而不是指针。 - 赋值运算符复制内容,而不是指针。考虑复制和交换习语。
- 移动构造函数复制指针,但使另一个对象无效。
- 移动赋值交换指针,或者分配一个指针并释放另一个。
该错误可能是由于缺少或错误了上述其中一项。在编译期间更容易捕获此类错误的一个好方法是使用 std::unique_ptr with a custom deleter 而不是手动释放。
请注意,如果使用任何复杂的代码,例如 T=vector 或 T=big num,您的代码将崩溃 and/or 内存泄漏。您可以添加 static_assert(std::is_trivial<T>::value);
以确保它不会被实例化,例如 std::map
.