MSVC Address Sanitizer - 有什么理由在发布版本中使用它吗?

问题描述

Microsoft 最近将 Address Sanitizer (ASan) 引入 Microsoft Visual Studio 2019,我一直在试验它。这个问题特定于 C 和 C++。我的问题是:是否有任何理由为发布版本启用 ASan,而不是仅对调试版本启用它?打开 ASan 对我的程序的性能和内存使用来说是毁灭性的。 (cpu 性能比减半还差,内存使用量增加了两倍。)因此,我希望是,如果我启用 ASan 只是为了检查潜在问题,并且它在调试版本中没有检测到任何问题,那么我可以安全地假设发布版本中不会有任何问题,否则 ASan 会发现?当然,我们不打算在发布/生产版本中启用 ASan?

感谢您的任何见解。

解决方法

因此我的希望是,如果我启用 ASan 只是为了检查潜在问题,并且它在 Debug 版本中没有检测到任何问题,那么我可以放心地假设 Release 版本中不会有任何问题否则被 ASan 抓住了?

这不太可能(尤其是对于较大的复杂程序)。考虑如下函数:

int array[250];

int test1(uint16_t a) {
    return array[ (1016 / (a+1)) & 0xFF];
}

您可以使用许多 a 值(例如 0、2、3、4、...)对其进行测试,它会很好,并且会在调试期间通过地址清理程序的测试。然后,在发布后,它可能会由于 a 的不同(未经测试)值(例如 1)触发“数组索引超出范围”错误而崩溃。

为了保证不会发生这样的事情,您可以测试每个函数的所有可能的参数组合(这将非常昂贵);但是(在存在全局变量/状态的情况下)这可能仍然不够,并且(在存在多个线程的情况下)它不会找到隐藏的竞争条件(例如,几乎总是有效的代码,因为线程 A 在线程 B 之前完成,导致崩溃当时间上的细微差异导致线程 B 在线程 A 之前完成时)。

我们当然不打算在发布/生产版本中启用 ASan?

正确 - 保持启用状态太昂贵了。

总体思路是将出现错误的风险降至最低(因为您不能保证所有错误都被发现并消除)。无需太多测试,您就可以说您“80% 确定”已发布版本中没有错误;并且通过启用 Asan(和优化)的一些严格测试,您可以说您“95% 确定”发布的版本中没有错误。

这真正归结为经济学(金钱)。这是“软件错误的成本(销售损失、支持成本等)”与“发现错误的成本”的妥协;像电脑游戏这样的东西可能没问题,但测试较少(因为用户只是假设游戏偶尔会崩溃)和像生命维持机器(错误导致死亡)之类的东西,你可能首先拒绝使用 C 或 C++。

另一件值得考虑的事情是,用户并不在意你的代码为什么会失败——如果它因为错误而失败,那么用户会很恼火;如果它因为 Asan 被启用并检测到错误而失败,那么用户也会同样恼火。在发布版本中启用 Asan 将有助于用户在错误报告中提交更好的信息,但大多数人不会提交错误报告(他们只是坐在那里很恼火;想知道这是否是暂时的硬件故障,因为它们太便宜了买不起) ECC RAM,或者如果它是操作系统或驱动程序中的错误;然后重新启动软件)

,

先入为主的事实:程序的形状 - 从广义上讲 - 属于两类之一。

  1. 其逻辑表示表示为其源代码。
  2. 它的二进制表示,由编译器(和链接器)翻译成机器可以执行的东西。

1. 是程序员希望程序执行的操作,而 2. 是程序将该意图转化为的内容。

理想情况下,1. 完全符合编程语言的规范,并且任何一种表示都具有相同的可观察行为。实际上,1. 是错误的,而 2. 会做任何事情。

因此练习是:评估 2. 被破坏的严重程度。要做到这一点,您绝对希望2.尽可能接近您的客户将运行的内容。在启用 ASan 的情况下,对编译为发布配置的 2. 进行模糊测试可以让您达到目标。如果您不喜欢阅读,请尽人类所能想象的努力模糊这个目标,然后随心所欲。

这涵盖了不容置疑的事实。以下是关于您(我们、我们)应该真正做什么的强烈意见。如果您不喜欢意见、强烈意见或道德规范,请停止阅读。