gcc -ftrapv

gcc に組み込みの「実行時算術オーバーフロー検出」機能 (-ftrapv) について除算に対応していないことを確認した。

$ gcc -ftrapv -x c -S -o - - << EOF
> void calc(int a, int b) {
> int w = a + b;
> int x = a - b;
> int y = a * b;
> int z = a / b;
> }
> EOF
        .file   ""
.globl __addvsi3
.globl __subvsi3
.globl __mulvsi3
        .text
.globl calc
        .type   calc, @function
calc:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $40, %esp
        movl    12(%ebp), %eax
        movl    %eax, 4(%esp)
        movl    8(%ebp), %eax
        movl    %eax, (%esp)
        call    __addvsi3
        movl    %eax, -16(%ebp)
        movl    12(%ebp), %eax
        movl    %eax, 4(%esp)
        movl    8(%ebp), %eax
        movl    %eax, (%esp)
        call    __subvsi3
        movl    %eax, -12(%ebp)
        movl    12(%ebp), %eax
        movl    %eax, 4(%esp)
        movl    8(%ebp), %eax
        movl    %eax, (%esp)
        call    __mulvsi3
        movl    %eax, -8(%ebp)
        movl    8(%ebp), %eax
        cltd
        idivl   12(%ebp)
        movl    %eax, -4(%ebp)
        leave
        ret
        .size   calc, .-calc
        .ident  "GCC: (GNU) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)"
        .section        .note.GNU-stack,"",@progbits

確かに加減乗算は _addvsi3, __subvsi3, __mulvsi3 の組み込み関数呼び出し (call) になっており、除算だけ x86 の idivl (整数除算機械語) になっている。

加減乗算のオーバーフローの発生条件と比較して、除算オーバーフローはほぼ起きない (除数が -1 で被除数が INT_MAX という組み合わせに限る) という実情と、チェックのための関数呼び出しのコストを考えてのことなんだろうな、というメモ。

ありがと > id:yupo5656:20051227:p1