除以零不会导致Nvidia Jetson出现运行时异常

Wos*_*ame 8 c arm integer-division divide-by-zero armv8

我对ARM处理器的内部细节不是很熟悉,但是我不了解Nvidia Jetson Nano开发板上的以下行为。

C代码示例...

//main.c

#include <stdio.h>

int main()
{
  int fred = 123;
  int i;

  for(i = -10 ; i <= 10 ; i++)
    printf("%d / %d == %d\n", fred, i, fred / i);

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译:

gcc main.c -ggdb
Run Code Online (Sandbox Code Playgroud)

运行生成的a.out可执行文件将产生以下输出...

123 / -10 == -12
123 / -9 == -13
123 / -8 == -15
123 / -7 == -17
123 / -6 == -20
123 / -5 == -24
123 / -4 == -30
123 / -3 == -41
123 / -2 == -61
123 / -1 == -123
123 / 0 == 0                  //unexpected!
123 / 1 == 123
123 / 2 == 61
123 / 3 == 41
123 / 4 == 30
123 / 5 == 24
123 / 6 == 20
123 / 7 == 17
123 / 8 == 15
123 / 9 == 13
123 / 10 == 12
Run Code Online (Sandbox Code Playgroud)

使用gcc 3.7在古老的Pentium 4上编译的代码完全相同,导致(按预期方式)i达到0并除以零时会抛出运行时异常。

Nvidia板运行的是Ubuntu 18.04 LTS,gcc版本7.4.0(最新),并且在其他方​​面都运行良好。我还编译了此代码的等效Ada语言版本,并引发了一个运行时异常,这人们所期望的(因为Ada代表我提前进行了安全检查)。

我意识到在C语言中,“零除会产生不确定的行为”可能是对此的解释,但是对于同一个编译器套件的两个版本而言,对同一操作给出如此不同的结果令我感到困惑。

哪种情况会使Nvidia Tegra ARM(64位)CPU允许除以零的值被操作系统忽略而未通过?

编辑:有关从/ etc / cpuinfo CPU的详细信息...

$ cat /proc/cpuinfo
processor       : 0
model name      : ARMv8 Processor rev 1 (v8l)
BogoMIPS        : 38.40
Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32
CPU implementer : 0x41
CPU architecture: 8
CPU variant     : 0x1
CPU part        : 0xd07
CPU revision    : 1

.... truncated ....
Run Code Online (Sandbox Code Playgroud)

Ale*_*op. 8

Nvidia Jetson Nano开发板使用基于ARMv8架构的ARM Cortex-A57(Link)。根据ARMv8 的指令集规范,被零除的整数将返回零且不会被捕获。

2.3分度指令

ARMv8-A支持32位和64位大小值的有符号和无符号除法。

指令说明

SDIV签名鸿沟

UDIV无符号除法

...

不会捕获溢出和被零除

•任何被零除的整数都将返回零

因此,sdiv在这种情况下,编译器会生成(请参见示例),并且CPU会毫无例外地返回0。在不同平台上编译相同代码时,彼此之间的CPU对除零的反应可能不同。正如您在问题中提到的那样,如果被0除,则C标准未定义行为。