【问题标题】:MSVC C/C++ compiler undefined behavior warningMSVC C/C++ 编译器未定义行为警告
【发布时间】:2020-05-15 02:41:09
【问题描述】:

我使用 Visual Studio 2019 编译了简单的 UB 代码,没有任何警告或错误:

int main()
{
    int i = 10;
    i = i++ + ++i;
    return i;
}

我已打开 EnableAllWarnings(/Wall) 并将警告视为错误 (/WX) 标志。 编译成:

mov         eax,17h  
ret  

因为编译器生成了这段代码,我确信他检测到了 UB。 为什么 MSVC 不生成任何关于 UB 的警告?

我已经检查了 Clang 和 GCC 是否为这个示例提供了警告。 他们是否会为任何可能的 UB 生成警告?如果是这样,为什么 MSVC 没有?

【问题讨论】:

  • 在未定义行为的情况下,允许编译器做他想做的事
  • 编译器不需要报告 UB。
  • 你确定它“检测到”了 UB 是什么? 23(十进制)似乎没有检测到任何特殊值。
  • 编译器没有检测到未定义的行为。它在编译时计算结果,因为它是一个经过优化的简单表达式。由于计算是未定义的行为,因此结果可以是任何东西。

标签: c++ visual-studio compiler-warnings undefined-behavior


【解决方案1】:

Clang 和 GCC 对此示例给出警告。它们是否会为任何可能的 UB 生成警告?

没有。许多事情被定义为“未定义的行为”而不是需要诊断,这正是因为它们极难(甚至理论上证明是不可能的)以 100% 的准确度检测。

【讨论】:

  • 不仅如此,最容易发现的错误往往是程序员最不可能真正犯的。
【解决方案2】:

假设代码是 *p = (*q)++ + ++(*r); 在这种情况下,编译器通常无法知道如果有任何指针组合将标识相同的对象,则编译器将无法知道。虽然让编译器在像您这样的简单代码 sn-ps 中发出诊断问题很简单,但与未能在碰巧识别相同对象的指针。除非作者或维护者编写代码来执行此操作,否则编译器不会对构造发出诊断。尽管一些编译器的编写者花费了大量精力来包括此类诊断,但许多其他人认为,他们在包括此类诊断方面可能花费的任何时间和精力都最好花在支持其他更有用的功能上。

【讨论】:

  • 然后还有未定义行为的更令人惊讶的含义,例如,如果编写编译器以识别(*q)++ + ++(*r) 中可能存在的未定义行为,那么它可能会注意当@ 时发生未定义行为987654323@与*r重叠,程序员负责避免UB,因此*q不重叠*r。它可以在q == r 时以不安全的方式继续优化其他(正确的)代码,因为它已经“证明”缺乏别名。
  • @BenVoigt:确实。该标准不努力判断什么样的行为保证会使实现或多或少适合各种目的,而是依赖编译器编写者来识别他们的客户认为有用的任何保证。因为某些实现是在程序不可能以比无用的方式表现更糟糕的情况下使用的,所以标准没有试图强制实现的行为方式不适合在以下情况下处理不可信数据的程序: ...
  • ...某些可能的程序行为(例如让恶意数据的创建者控制机器)将是无法容忍的。请注意,与 clang 和 gcc 的制造者所声称的相反,未定义的行为意味着委员会将某些构造视为 其管辖范围之外。在某些情况下,委员会甚至表示,尽管没有任何实现以这种方式运行的实际要求,但它希望某些操作由普通实现处理。
  • 这不仅仅是导致 UB 超出标准管辖范围的构造,而是执行该构造的整个程序的行为。标准在这一点上是具体的。
  • @BenVoigt:根据该标准的作者,“它[未定义的行为] 还确定了可能符合语言扩展的区域:实现者可以通过提供官方未定义行为的定义来扩充语言。 "虽然利用此类扩展的程序可能是不可移植的,并且它们的行为超出了标准的管辖范围,但标准的作者明确承认 C 程序不需要是可移植的,并且 C 的优势之一是能够不可移植的代码来完成原本不可能的事情。
【解决方案3】:

在clang中你可以这样使用:

clang++-fsanitize=undefinedtest.cpp

程序运行时会报that之类的错误

visual studio 已经supportsaddress_sanitizer。 看来 UndefinedBehaviorSanitizer 将不得不wait a while

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多