Подтвердить что ты не робот

Различные результаты для команды idiv

Взгляните на этот фрагмент кода

int main(int argc)
{
    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;
}

Он вызывает поведение undefined на типичной платформе, но "поведение" сильно отличается от того, что я ожидаю, - оно действует так, как будто это бесконечный цикл. Я могу думать о сцене, которую он кусает.

Конечно, undefined есть undefined, но я проверил выходную сборку, она использует обычную idiv - почему она не ловушка? Для сравнения, деление на ноль вызывает немедленное прерывание.

Использование Windows 7 64 бит и MingW64

Может кто-нибудь объяснить это мне?

ИЗМЕНИТЬ

Я просто нашел, что подпись main неверна, но это не имеет значения.

Я попробовал несколько вариантов, и результаты всегда были одинаковыми.

Вот сборка:

    .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"
4b9b3361

Ответ 1

Бесконечный цикл, который вы наблюдаете, возможно, является ошибкой в ​​MinGW-w64.

MinGW-w64 частично поддерживает SEH, и если вы запустите свой код в отладчике, вы увидите, что обработчик исключений (функция с именем "_gnu_exception_handler" ) вызывается в результате недопустимого idiv. (например, запустите свою программу в gdb и установите точку останова на _gnu_exception_handler)

Просто сказано, что этот обработчик исключений в случае переполнения целых чисел просто отклоняет исключение и продолжает выполнение в точке, где произошло исключение (idiv). Затем операция idiv выполняется снова, в результате один и тот же триггер переполнения тот же обработчик ошибок, и ваш процессор перемещается между idiv и обработчиком исключений. (Здесь поведение MinGW-w64 можно рассматривать как ошибку.)

Вы можете увидеть его прямо в исходном здесь, если хотите углубляться.

Значение "EXCEPTION_CONTINUE_EXECUTION", возвращаемое _gnu_exception_handler, когда оно связано с EXCEPTION_INT_OVERFLOW (целочисленным переполнением), является тем, что подпитывает это поведение (когда система видит, что обработчик возвращает EXCEPTION_CONTINUE_EXECUTION, он переходит к инструкции, которая генерирует исключение, и пытается выполните его снова.)

Если вас интересует более подробная информация, здесь - это хорошие ресурсы, чтобы понять, как работает SEH в Windows.