Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 被零除不会在Nvidia Jetson上导致运行时异常_C_Arm_Integer Division_Divide By Zero_Armv8 - Fatal编程技术网

C 被零除不会在Nvidia Jetson上导致运行时异常

C 被零除不会在Nvidia Jetson上导致运行时异常,c,arm,integer-division,divide-by-zero,armv8,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

我不太熟悉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;
}
运行生成的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
使用gcc 3.7在古代奔腾4上编译的完全相同的代码会在
i
达到0时引发运行时异常,并导致被零除

Nvidia主板运行的是Ubuntu18.04LTS,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 ....

Nvidia Jetson纳米开发板使用基于ARMv8架构的ARM Cortex-A57()。 基于ARMv8的指令集,整数除以零返回零,且不被捕获

2.3分割指令

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

指令说明

有符号除法

无符号除法

溢出和被零除不被捕获:

•任何整数除以零返回零


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

值得注意的是,并非所有的ARM处理器都是相同的(如前所述)。我正在使用STM32L4(包含cortex-m4)进行一个项目。它有SDIV和UDIV指令。但是,可配置零除异常的生成(参见,第231页)


更复杂的是,编译器有时可以识别除法为零的情况,并生成非法指令(排除我提到的配置)。玩一下这个。

你能检查一下
FPSCR->DZE
是否设置好了吗。它是
除零异常启用位
。它可能也适用于整数。@FiddlingBits它似乎是在Linux下运行的(我想是用户空间吧?)。所以我想这是关于信号陷阱的处理。嗯,也许内核没有配置为设置这个位…@EugeneSh。是用户空间,以非根用户身份运行,没有特权。相关问题:它是什么ARM体系结构?基于此:在被零除的情况下可能会有不同的行为。例如,在ARMv7-A上,除以零总是返回一个零的结果。我以前从未意识到,不同的体系结构处理这些事情的方式如此不同。我曾愚蠢地认为,像POSIX所要求的那样,这样一个基本的事情总是会导致一个硬SIGFPE。迷人的。谢谢您的努力。@Wossname您能分享POSIX要求整数除零的位置吗
SIGFPE
?我发现,用
FPE_INTDIV
值提升
SIGFPE
是可选的:“实现可能[…]包含扩展或限制,阻止生成某些值。”
$ 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 ....