我应该默认使用三种互斥的 Clang 消毒剂中的哪一种?

Which of the three mutually exclusive Clang sanitizers should I default to?

Clang 有 a number of sanitizers that enable runtime checks for questionable behavior. Unfortunately, they can't all be enabled at once.

It is not possible to combine more than one of the -fsanitize=address, -fsanitize=thread, and -fsanitize=memory checkers in the same program.

更糟糕的是,这三者中的每一个似乎都太有用了,不能忽略。 AddressSanitizer 检查内存错误,ThreadSanitizer 检查竞争条件,MemorySanitizer 检查未初始化的读取。 我担心所有这些事情!

显然,如果我对错误所在的位置有预感,我可以根据它来选择消毒剂。但如果我不这样做呢?更进一步,如果我想将消毒剂用作预防工具而不是诊断工具,以指出我什至不知道的错误怎么办?

换句话说,鉴于我没有特别寻找任何东西,默认情况下我应该使用哪种消毒剂进行编译?我是否只是希望编译和测试整个程序三次,每种消毒剂一次?

正如您所指出的,消毒剂通常是相互排斥的(您可以通过 -fsanitize=address,undefined,leak 仅组合 Asan+UBsan+Lsan,如果您的程序不包含故意的,也可以通过 -fsanitize=...,integer 添加 Isan无符号溢出)所以确保完整覆盖的唯一方法是对它们中的每一个进行单独的 QA 运行(这意味着为每个 运行 重建 SW)。顺便说一句,还建议用 Valgrind 做另一个 运行。

在生产中使用牙山有两个方面。一方面,普遍的经验是某些错误 只能 在生产中检测到,因此您 do 想偶尔 运行 清理那里的构建,增加测试覆盖率 [*]。另一方面,据报道 Asan 在某些情况下 增加 攻击面(参见例如 this oss-security report),因此将其用作强化解决方案(以防止错误而不是检测错误)具有气馁了。

[*] 作为旁注,Asan 开发人员还强烈建议使用模糊测试来增加覆盖率(参见 Cppcon15 and CppCon17 会谈)。

[**] 请参阅 Asan FAQ 以了解使 AddressSanitizer 更严格的方法(查找 "aggressive diagnostics")