为何检测到的内存泄漏大小大于对象分配的内存大小?
内存泄漏疑问:Direct Leak为40字节的原因分析
问题代码
#include <iostream> using namespace std; typedef struct Resource{ int fee; // 4 bytes }; class MyClass { public: MyClass( string teacher, Resource * res ) : teacher_(teacher), res_(res) { } ~MyClass() { // delete res_; // cause indirect leak } private: string teacher_; Resource * res_; }; int main(){ Resource * res = new Resource; res->fee=100; cout<<"size of Resource "<<sizeof(res)<<endl; MyClass * cl = new MyClass("Tom", res); cl = new MyClass ("Joh", res); cout<<"size of My Class "<<sizeof(cl)<<endl; delete cl; }
Address Sanitizer检测结果
size of Resource 8 size of My Class 8 Program stderr ================================================================= ==1==ERROR: LeakSanitizer: detected memory leaks Direct leak of 40 byte(s) in 1 object(s) allocated from: #0 0x7f863ac55518 in operator new(unsigned long) (/opt/compiler-explorer/gcc-13.2.0/lib64/libasan.so.8+0xdb518) (BuildId: 5ce9c09d3612315d01d50bcaafaea176e7ddab77) #1 0x402445 in main /app/example.cpp:25 #2 0x7f863a5d3082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee) Indirect leak of 4 byte(s) in 1 object(s) allocated from: #0 0x7f863ac55518 in operator new(unsigned long) (/opt/compiler-explorer/gcc-13.2.0/lib64/libasan.so.8+0xdb518) (BuildId: 5ce9c09d3612315d01d50bcaafaea176e7ddab77) #1 0x4023c4 in main /app/example.cpp:22 #2 0x7f863a5d3082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee) SUMMARY: AddressSanitizer: 44 byte(s) leaked in 2 allocation(s).
疑问点
- 间接泄漏(indirect leak)大小为4字节,对应
Resource结构体中int类型成员的内存块。 - 直接泄漏(direct leak)大小为40字节,既不是
MyClass指针大小(8字节)也不是MyClass与Resource对象大小的和,原因是什么?
原因分析
指针大小的误区:你打印的
sizeof(res)和sizeof(cl)都是64位系统下指针的大小(8字节),而非对象本身的实际大小。sizeof(Resource)实际为4字节(仅包含一个int成员),sizeof(MyClass)则是std::string的大小加上Resource*指针的大小,在你的编译环境中这个总和恰好是40字节。直接泄漏的来源:直接泄漏的40字节对应第一个
MyClass对象。在main函数中,你先创建new MyClass("Tom", res)并赋值给cl,随后直接让cl指向新的MyClass("Joh", res),导致第一个MyClass对象的内存地址丢失,从未被delete释放。这个对象本身的内存大小就是40字节,因此ASAN将其标记为直接泄漏。间接泄漏的来源:间接泄漏的4字节是
Resource对象的内存。你通过new Resource分配了4字节内存,两个MyClass对象都持有该内存的指针。由于第一个MyClass对象泄漏,其持有的res_指针无法被访问,进而导致Resource的内存无法被释放,因此ASAN将其标记为间接泄漏(依赖于泄漏对象的内存块)。
内容的提问来源于stack exchange,提问作者Minh Pham
相关产品推荐
相关产品推荐

