Memory/Address 消毒剂与 Valgrind

Memory/Address Sanitizer vs Valgrind

我想要一些工具来诊断释放后使用错误和未初始化的错误。我正在考虑 Sanitizer(Memory and/or Address) 和 Valgrind。但是我对它们的优点和缺点知之甚少。谁能说出Sanitizer和Valgrind的主要特点、区别和pros/cons?

编辑:我发现了一些比较,例如:Valgrind 使用 DBI(动态二进制检测)而 Sanitizer 使用 CTI(编译时检测)。 Valgrind 使程序慢得多(20 倍)是否 Sanitizer 运行速度比 Valgrind 快得多(2 倍)。如果有人能给我一些更重要的考虑点,那将是一个很大的帮助。

我想你会发现这个 wiki 有用。

TLDR 消毒剂的主要优点是

  • CPU 开销小得多(Lsan 实际上是免费的,UBsan 是 1.25 倍,Asan 和 Msan 对于计算密集型任务是 2-4 倍,对于 GUI 是 1.05-1.1 倍,Tsan 是 5-15 倍)
  • 更广泛的 class 检测到的错误(堆栈和全局溢出,使用后 return)
  • 完全支持多线程应用程序(Valgrind 对多线程的支持是个笑话)
  • 内存开销小得多(Asan 高达 2 倍,Msan 高达 3 倍,Tsan 高达 10 倍,这比 Valgrind 好得多)

缺点是

  • 更复杂的集成(你需要教你的构建系统理解 Asan,有时在 Asan 中解决 limitations/bugs,你还需要使用相对较新的编译器)
  • MemorySanitizer 目前还不是很容易使用,因为它需要重建 Msan 下的所有依赖项(包括所有标准库,例如 libstdc++);这意味着临时用户只能使用 Valgrind 来检测未初始化的错误
  • 消毒剂通常不能相互组合(唯一受支持的组合是 Asan+UBsan+Lsan),这意味着您必须进行单独的 QA 运行才能捕获所有类型的错误

一个很大的区别是 LLVM-included memory and thread 消毒剂隐式映射了大量的地址 space(例如,通过调用 mmap(X, Y, 0, MAP_NORESERVE|MAP_ANONYMOUS|MAP_FIXED|MAP_PRIVATE, -1, 0) 跨越 TB 的地址 space 在 x86_64 环境中)。即使他们不一定分配该内存,映射也会对限制性环境造成严重破坏(例如,ulimit 值具有合理设置的环境)。