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

ASAN在CMake Debug配置下检测到内存泄漏,Release下未检测到,原因何在?

问题:Release构建下ASAN无法检测到内存泄漏?

我写了一个存在内存泄漏的C程序,通过CMake Debug配置构建并运行时,ASAN可正常检测到该泄漏;但切换至Release配置构建运行时,ASAN却显示无内存泄漏。使用CMake 3.8.x和3.9.x版本,基于C11测试,通过CLION或命令行指定CMAKE_BUILD_TYPE均出现相同现象。尝试修改编译选项、设置ASAN_OPTIONS和LSAN_OPTIONS后问题仍未解决。

main.cpp

#include <ios>
#include <iostream>
#include <fstream>
#include <string>
#include <chrono>

using namespace std;
using namespace std::chrono;

int main(int argc, char **argv) {
    std::cout << "Hello, World!\n";
    int *i = new int[10]; // 产生内存泄漏的代码
    int j = rand()%9;
    std::cout<<"j="<<j<<std::endl;
    if(j<0||j>9) return 0;
    *(i+j) = 77;
    std::cout<<"i="<<*(i+j)<<std::endl;
    return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.1)

project(leakTest)

set(CMAKE_BUILD_RPATH "$ORIGIN")

if (CMAKE_VERSION VERSION_LESS "3.1")
    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
else ()
  set (CMAKE_CXX_STANDARD 11)
endif ()

add_compile_options(-fsanitize=address)
add_link_options(-fsanitize=address)
add_executable(usingLeakTest main/src/main.cpp)

原因分析

  • 编译器死代码消除优化:Release模式下默认开启-O2级优化,编译器会分析代码逻辑,发现new int[10]分配的内存除了写入单个元素外,没有其他被依赖的场景(比如未将指针传递给外部函数、未读取数组其他元素,且程序退出后系统会自动回收进程内存),因此会直接消除这个堆分配操作——要么改用栈内存,要么完全跳过分配。既然内存根本没在堆上分配,ASAN自然检测不到泄漏。

  • ASAN与Release优化的兼容性限制:尽管ASAN支持Release构建,但部分激进优化会破坏其内存跟踪机制。死代码消除就是典型案例,它会移除ASAN本应跟踪的内存分配指令,直接导致漏报。

  • 验证与解决方法:

    • 手动关闭死代码消除:在CMake中为Release模式添加编译选项-fno-dead-code-elimination,比如修改CMakeLists.txt,添加set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-dead-code-elimination")。
    • 修改代码让内存分配被视为必要操作:比如在main函数末尾添加std::cout << "内存指针地址:" << i << std::endl;,让编译器认为指针i被实际使用,不会消除分配操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 23:57:22