42

我想要一些工具来诊断释放后使用错误和未初始化的错误。我正在考虑消毒剂(内存和/或地址)和 Valgrind。但我对它们的优缺点知之甚少。谁能说出 Sanitizer 和 Valgrind 的主要特点、区别和优缺点?

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

4

2 回答 2

47

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

TLDR 消毒剂的主要优点是

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

缺点是

  • 更复杂的集成(您需要教您的构建系统了解 Asan,有时还需要解决 Asan 本身的限制/错误,您还需要使用相对较新的编译器)
  • MemorySanitizer 目前并不容易使用,因为它需要重建 Msan 下的所有依赖项(包括所有标准库,例如 libstdc++);这意味着普通用户只能使用 Valgrind 来检测未初始化的错误
  • 消毒剂通常不能相互组合(唯一支持的组合是 Asan+UBsan+Lsan),这意味着您必须进行单独的 QA 运行才能捕获所有类型的错误
于 2017-11-13T10:19:58.420 回答
2

一个很大的区别是,包含 LLVM 的内存线程清理程序隐式映射了大量的地址空间(例如,通过mmap(X, Y, 0, MAP_NORESERVE|MAP_ANONYMOUS|MAP_FIXED|MAP_PRIVATE, -1, 0)在 x86_64 环境中跨 TB 的地址空间进行调用)。即使它们不一定分配该内存,映射也会对限制性环境(例如,具有合理ulimit值设置的环境)造成严重破坏。

于 2019-06-04T21:04:12.027 回答