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

AddressSanitizer未检测到内存泄漏:是预期行为还是Bug?

内存泄漏检测差异:Valgrind报漏但AddressSanitizer无输出的原因

问题背景

以下C++程序存在内存泄漏:

#include <new>
#include <memory>

template <class T> class AlignedStorage {
    union {
        T t;
    };
public:
    AlignedStorage() {}
    ~AlignedStorage() {}
    T* data() {
        return &t;
    }
};

int main() {
    using T = std::unique_ptr<int>;
    AlignedStorage<T> s;
    new (s.data()) T(new int(42));
}

使用g++ -O0 -g file.cpp编译后,通过Valgrind运行得到泄漏报告:

LEAK SUMMARY:
definitely lost: 4 bytes in 1 blocks
indirectly lost: 0 bytes in 0 blocks
  possibly lost: 0 bytes in 0 blocks
still reachable: 0 bytes in 0 blocks
      suppressed: 0 bytes in 0 blocks

但使用g++ -O0 -g -fsanitize=address file.cpp编译并运行时,AddressSanitizer(ASAN)未输出任何错误信息。需要解答:

  1. 这是预期行为还是ASAN的Bug?
  2. ASAN是否无法检测所有内存泄漏?若如此,它具体能检测哪些类型的内存泄漏?

解答

这是预期行为,并非ASAN的Bug

这个场景下ASAN不报告泄漏是正常的,核心原因是两者的泄漏检测逻辑不同:

  • ASAN的泄漏检测逻辑是在程序退出时扫描堆内存块,判断是否存在栈/全局变量的引用指向这些块。在本例中,std::unique_ptr<int>对象被放在栈内存的union成员中,虽然我们没调用它的析构函数,但unique_ptr内部的指针成员仍指向new int(42)分配的堆内存,ASAN会认为这块堆内存是可达的,因此不会标记为泄漏。
  • 而Valgrind会追踪每个内存分配的完整生命周期,它能识别出unique_ptr的析构函数未被执行,导致其管理的内存没有被主动释放,因此标记为明确泄漏。

ASAN无法检测所有内存泄漏

ASAN的内存泄漏检测有明确的适用范围,它主要能检测以下类型的泄漏:

  • 完全无引用的堆内存:程序退出时,堆上的内存块没有任何栈指针、全局指针或其他堆指针指向它,这类泄漏会被ASAN明确报告。
  • 关联对象不可达导致的间接泄漏:比如某个结构体对象不可达时,其成员指针指向的堆内存也会被标记为泄漏。

但ASAN对以下场景的泄漏无能为力:

  • 栈/全局对象未析构导致的间接泄漏:像本例中,栈上的智能指针没执行析构,导致其管理的内存未释放,但只要指针本身还在栈/全局内存中保留着指向堆的引用,ASAN就会判定堆内存可达,不会报漏。
  • 手动管理内存但指针仍存在的泄漏:比如栈上声明int* p = new int;后未调用delete,程序退出时p仍在栈上,ASAN会认为堆内存有引用,不会报告泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 04:33:13