valgrind仅支持linux(部分bsd),需动态链接、禁用优化(-o0)、保留调试符号(-g);asan需编译链接均加-fsanitize=address并设asan_options;二者不可共存,应分阶段使用。

Valgrind 在 Linux 上跑不起来?先确认这三件事
Valgrind 本身不支持 macOS 和 Windows,只在 Linux(或部分 BSD)上可用,而且要求程序是动态链接的。静态链接的二进制、用了 __attribute__((constructor)) 过多的初始化逻辑、或者启用了某些内核级防护(如 ptrace 被禁用),都会导致 valgrind 启动失败或报 Illegal instruction。
- 检查是否在 Ubuntu/Debian 系统上安装了完整版:
sudo apt install valgrind(别只装valgrind-dbg) - 编译时务必关闭优化(
-O0),并保留调试符号(-g),否则行号和函数名全丢失 - 避免用
std::thread+fork()混用——Valgrind 对 fork 后的子进程跟踪不稳定,容易漏报
AddressSanitizer 报 heap-use-after-free 却找不到源头?
ASan 默认只显示崩溃点,不追溯分配位置。想定位原始 malloc 或 new 行,必须加运行时标志,而且得在编译时就埋好钩子。
- 编译加
-fsanitize=address -g,链接也得带-fsanitize=address(CMake 中要设CMAKE_CXX_FLAGS和CMAKE_EXE_LINKER_FLAGS) - 运行前设环境变量:
ASAN_OPTIONS=detect_stack_use_after_return=true:abort_on_error=true - 如果用的是 C++17 的
std::pmr::memory_resource或自定义分配器,ASan 默认不拦截——得手动调用__asan_poison_memory_region和__asan_unpoison_memory_region
为什么 Valgrind 说没泄漏,但 RSS 内存持续上涨?
Valgrind 只检测堆内存(malloc/new 分配的),对 mmap/mprotect 分配的大块内存、线程栈、共享库数据段、甚至 std::string 的 SSO 缓冲区都不管。RSS 上涨 ≠ 堆泄漏。
- 用
pmap -x <pid></pid>查看各内存段大小,重点关注[anon]和stack - 怀疑线程泄漏?查
/proc/<pid>/status</pid>里的Threads:字段,再结合ps -T -p <pid></pid> -
std::unordered_map插入大量元素后不 shrink,会持有远超实际需要的 bucket 数组——这不是泄漏,但 Valgrind 不提醒你
ASan 和 Valgrind 能不能一起用?
不能。二者都靠插桩或二进制重写拦截内存操作,同时启用会冲突,轻则报错退出,重则触发未定义行为。选一个就行:开发阶段用 ASan(快、报错准),发布前回归用 Valgrind(覆盖更全,能发现 ASan 漏掉的未初始化读)。
立即学习“C++免费学习笔记(深入)”;
- ASan 编译产物体积大、运行慢 2–3 倍,但能在几秒内复现问题
- Valgrind 运行慢 10–50 倍,且对多线程程序的误报率略高(比如条件变量唤醒顺序被重排)
- CI 流水线里建议优先跑 ASan,Valgrind 留给 nightly 手动触发
真正难搞的是跨模块内存管理——比如 A 库用 new 分配、B 库用 free 释放,ASan 和 Valgrind 都可能沉默。这种得靠统一 allocator + 静态分析工具辅助。








