You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何检测到的内存泄漏大小大于对象分配的内存大小?

内存泄漏疑问: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对象大小的和,原因是什么?

原因分析

  1. 指针大小的误区:你打印的sizeof(res)和sizeof(cl)都是64位系统下指针的大小(8字节),而非对象本身的实际大小。sizeof(Resource)实际为4字节(仅包含一个int成员),sizeof(MyClass)则是std::string的大小加上Resource*指针的大小,在你的编译环境中这个总和恰好是40字节。

  2. 直接泄漏的来源:直接泄漏的40字节对应第一个MyClass对象。在main函数中,你先创建new MyClass("Tom", res)并赋值给cl,随后直接让cl指向新的MyClass("Joh", res),导致第一个MyClass对象的内存地址丢失,从未被delete释放。这个对象本身的内存大小就是40字节,因此ASAN将其标记为直接泄漏。

  3. 间接泄漏的来源:间接泄漏的4字节是Resource对象的内存。你通过new Resource分配了4字节内存,两个MyClass对象都持有该内存的指针。由于第一个MyClass对象泄漏,其持有的res_指针无法被访问,进而导致Resource的内存无法被释放,因此ASAN将其标记为间接泄漏(依赖于泄漏对象的内存块)。

内容的提问来源于stack exchange,提问作者Minh Pham

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 16:58:20