nty*_*sdd 13 c integer-division undefined-behavior mingw-w64
看看这段代码
int main()
{
    int i = 1U << 31; // assume this yields INT_MIN
    volatile int x;
    x = -1;
    x = i / x; //dividing INT_MIN by -1 is UB
    return 0;
}
它在典型平台上调用未定义的行为,但"行为"与我的预期完全不同 - 它就好像它是一个无限循环.我能想到它咬人的场景.
当然未定义是未定义的,但我检查了输出程序集,它使用了一个简单的idiv- 为什么它不陷阱?为了便于比较,除以零会导致立即中止.
使用Windows 7 64位和MingW64
任何人都可以向我解释这个吗?
编辑
我尝试了几个选项,结果总是一样的.
这是集会:
    .file   "a.c"
    .def    __main; .scl    2;  .type   32; .endef
    .section    .text.startup,"x"
    .p2align 4,,15
    .globl  main
    .def    main;   .scl    2;  .type   32; .endef
    .seh_proc   main
main:
    subq    $56, %rsp
    .seh_stackalloc 56
    .seh_endprologue
    call    __main
    movl    $-1, 44(%rsp)
    movl    $-2147483648, %eax
    movl    44(%rsp), %ecx
    cltd
    idivl   %ecx
    movl    %eax, 44(%rsp)
    xorl    %eax, %eax
    addq    $56, %rsp
    ret
    .seh_endproc
    .ident  "GCC: (x86_64-posix-sjlj, built by strawberryperl.com project) 4.8.2"
小智 5
您观察到的无限循环可以说是MinGW-w64中的错误。
MinGW-w64部分支持SEH,并且如果您在调试器中运行代码,您将看到由于无效的idiv导致调用了异常处理程序(名为“ _gnu_exception_handler”的函数)。(例如,在gdb中运行程序并在_gnu_exception_handler上设置断点)
简而言之,在整数溢出的情况下,此异常处理程序的作用只是消除异常并在发生异常的位置继续执行(idiv)。然后再次执行idiv操作,导致相同的溢出触发相同的错误处理程序,并且CPU在idiv和异常处理程序之间来回移动。(在这里,可以将MinGW-w64的行为视为错误。)
如果您想深入了解,可以在这里直接在源代码中看到它。
_gnu_exception_handler处理EXCEPTION_INT_OVERFLOW(整数溢出)时,_gnu_exception_handler返回的值“ EXCEPTION_CONTINUE_EXECUTION”是助长此行为的原因(当系统看到处理程序返回EXCEPTION_CONTINUE_EXECUTION时,它将跳回到生成异常并尝试再次执行该异常的指令)
如果您对更多细节感兴趣,这里是了解SEH在Windows上如何工作的好资源。