【问题标题】:Why integer division by zero doesn't crash the program compiled with gcc?为什么整数除以零不会使用 gcc 编译的程序崩溃?
【发布时间】:2021-03-28 18:19:53
【问题描述】:

整数除以零是未定义的,应该会导致浮点异常,这就是我编写以下代码的原因

 int j = 0 ;
 int x = 1 / j;

在这种情况下,程序只是与 FPE 一起崩溃,但如果我不使用变量并且将使用像这样的文字值 int x = 1 / 0; 程序不会崩溃,而只是为 x 分配一些随机值!我试图通过添加自定义SIGFPE 处理程序来检测int x = 1 / 0; 是否真的导致崩溃,但我认为它在字面零除法期间从未被调用,但是当我首先将0 存储在变量中时它确实如此。因此,似乎字面上的零除法实际上从未使程序崩溃(我的意思是除法本身永远不会发生),在这种情况下,编译器(在我的情况下为 GCC)执行任何技巧(例如,用随机数替换 0) ?还是我误解了什么?

【问题讨论】:

  • 使用浮点数,整数除以零是UB,因此编译器没有义务发出任何信号
  • 1 / 0 可能不是在运行时完成,而是由编译器完成。它的值是未定义的。
  • MS Visual C 发出 编译器 错误:除以零或取模
  • 不,未定义就是未定义。
  • 这种未定义行为与所有其他未定义行为有何不同?

标签: c gcc


【解决方案1】:

为什么整数除以零不会导致用 gcc 编译的程序崩溃?

嗯,我认为答案是:因为它可以。它可能会崩溃。它不会崩溃。

还是我误解了什么?

来自C11 6.5.5p5(强调我的:p):

/ 运算符的结果是第一个操作数除以第二个操作数的商; % 运算符的结果是余数。在这两种操作中,如果第二个操作数的值为零,则行为未定义

The behavior is not defined。没有定义应该发生什么。它可能会“崩溃”。它不能崩溃。可以spawn nasal demons。该程序可以做任何事情。

您应该只编写您知道它们将如何运行的程序。如果您希望您的程序“崩溃”,请致电abort()

在这种情况下,编译器(在我的例子中是 GCC)是否执行任何技巧(例如用随机数替换 0)?

知道的唯一方法是检查生成的汇编代码。你可以使用https://godbolt.org/

【讨论】:

  • 引文做得很好。
【解决方案2】:

由于表达式包含除以零常数,gcc 可以在编译时处理该问题。

如果除以变量值为 0,编译器将把责任交给异常处理程序,因为计算是不可预测的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-26
    • 2011-03-17
    相关资源
    最近更新 更多