【问题标题】:MSVC Address Sanitizer - Any reason to use it in Release builds? [closed]MSVC Address Sanitizer - 有什么理由在 Release 版本中使用它? [关闭]
【发布时间】:2021-08-23 12:14:49
【问题描述】:

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

感谢您的任何见解。

【问题讨论】:

  • Address Sanitizer 对于查找仅在启用优化时暴露的错误非常有用。考虑使用 ASan 为 Release 创建第三个构建目标。
  • @RichardCritten 绝对 - 我很久以前将我的“发布”配置拆分为“开发”和“发布”。
  • 如果您有集成/系统测试套件,请使用优化的发布版本和 ASan 运行它。

标签: c++ c windows address-sanitizer msvc12


【解决方案1】:

因此,我希望如果我启用 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,或者如果它是操作系统或驱动程序中的错误;然后重新启动软件。

【讨论】:

  • “正确 - 启用太贵了。” - 一旦内存安全问题导致您的服务泄露私人信息,导致您的公司破产,您将重新考虑,或者让你的火星车无用。
  • @IInspectable:在这些情况下,“你可能一开始就拒绝使用 C 或 C++”。随意将“运行 Asan 的 C 或 C++”的性能与 Java(或 Ada 或 Rust 或..)等更安全的东西进行基准测试。
  • 除非您 100% 确定,否则对堆栈没有边界检查没有任何借口。它可能会导致非常直接的安全问题,并且进行无分支边界检查或“不太可能”失败的分支不会有明显的成本。如果你需要速度的每一点,那么你必须检查每一个输入,没有任何借口。
  • @IInspectable:您是否建议人们在编译 Linux 内核(或 JVM 或..)时应该(例如)启用 Asan?所有这些东西都没有阿桑,所以......
  • 是的。这正是我的建议。除非您激励公司和组织提供不臭的软件,否则这种情况不会发生。现在的现实是,每次数据泄露都会在几周内成为头条新闻,然后再回到我们一直以来的做事方式。让组织为疏忽付出代价,为造成的真正损害付出代价,我们将开始在野外看到像 ASan 这样的发布版本。只要发布垃圾软件更有利可图,我们就会到处看到垃圾软件。
【解决方案2】:

预先确定的事实:程序的形状 - 从广义上讲 - 属于两个类别之一。

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

1. 是程序员希望程序执行的操作,2. 是程序将该意图翻译成的内容。

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

练习是这样的:评估2. 被破坏的严重程度。为此,您绝对希望2. 尽可能接近您的客户将运行的内容。在启用 ASan 的情况下,对编译为发布配置的 2. 进行模糊测试可以让您到达那里。如果您不想继续阅读,请尽人类所能想象的那样对这个目标进行模糊测试,然后尽情享受吧。

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


【讨论】:

  • 您似乎专注于发布前测试(毫无疑问,Asan 的好处)您的软件,而不是在预发布测试期间)。
  • @bre 我将在<hr/> 下方介绍该部分,一旦我了解它。不,我不建议在发货前删除 ASan。
猜你喜欢
  • 2016-12-25
  • 2011-10-12
  • 2023-04-06
  • 2019-06-06
  • 2017-10-09
  • 2022-01-23
  • 2015-11-16
  • 2021-12-02
  • 2013-06-25
相关资源
最近更新 更多