必须显式配置MEMORYCHECK_COMMAND_OPTIONS,否则CTest调用Valgrind时缺关键参数会导致漏报;需设为"--leak-check=full --show-leak-kinds=all --track-origins=yes",且find_program(MEMORYCHECK_COMMAND NAMES valgrind)须置于enable_testing()之前,测试目标必须为可执行文件,详细报告仅存于Testing/Temporary/MemoryChecker.*.log中。

CTest 集成 Valgrind 时必须设 MEMORYCHECK_COMMAND_OPTIONS
CTest 默认调用 valgrind 但不带任何参数,漏掉关键选项会导致漏报(比如只报 definitely lost,忽略 still reachable 或未初始化访问)。必须显式配置参数,不能依赖默认行为。
-
set(MEMORYCHECK_COMMAND_OPTIONS "--leak-check=full --show-leak-kinds=all --track-origins=yes")是最低可用组合 - 如果项目含多进程或子进程(如 fork + exec),加
--trace-children=yes - 避免用
--tool=memcheck:CTest 已固定使用 memcheck,重复指定会报错
CMakeLists.txt 中 find_program(MEMORYCHECK_COMMAND NAMES valgrind) 要放在 enable_testing() 前
顺序错会导致 CTest 找不到 Valgrind,运行 ctest -T memcheck 时直接跳过内存检查,输出里连 “Memcheck” 字样都不出现。
- 正确位置:在
include(CTest)和enable_testing()之间 - 可加
REQUIRED强制失败提示:find_program(MEMORYCHECK_COMMAND NAMES valgrind REQUIRED) - 若 Valgrind 不在 PATH(如装在
/opt/valgrind-3.20.0/bin/valgrind),需提前set(ENV{PATH} "/opt/valgrind-3.20.0/bin:$ENV{PATH}")
测试目标必须链接可执行文件,不能只测静态库
add_test 的 COMMAND 必须指向最终可执行文件($<my_app></my_app>),对 add_library 目标跑 memcheck 无效——Valgrind 只能检测运行时行为,不分析目标文件本身。
- 错误写法:
add_test(NAME lib_test COMMAND my_lib)→ 报错或静默跳过 - 正确写法:
add_executable(my_app main.cpp); add_test(NAME app_test COMMAND $<my_app>)</my_app> - 如果想测库逻辑,必须包装成一个调用该库的 minimal main 函数
运行 ctest -T memcheck 后,详细报告不在终端而在日志文件里
终端只显示 “Passed” 或 “Failed”,真正泄漏堆栈、行号、起源跟踪全在 Testing/Temporary/MemoryChecker.*.log。很多人卡在这一步,以为没检测到问题,其实是没去翻日志。
- 路径示例:
build/Testing/Temporary/MemoryChecker.12345.log - 关键线索:日志里含
==12345==这种 PID 前缀,和终端输出一致,可对应查找 - 若日志为空,大概率是编译没开
-g或CMAKE_BUILD_TYPE不是Debug
MEMORYCHECK_COMMAND_OPTIONS 全对,只要可执行文件没 -g,日志里就只有地址、没有 main.cpp:42 这种行号。


















