Neden GCC ile x 86 tamsayı taşması sonsuz bir döngüye neden olur mu? | Netgez.com
SORU
7 EKÄ°M 2011, Cuma


Neden GCC ile x 86 tamsayı taşması sonsuz bir döngüye neden olur mu?

Aşağıdaki kodu GCC sonsuz bir döngüye gider:

#include <iostream>
using namespace std;

int main(){
    int i = 0x10000000;

    int c = 0;
    do{
        c  ;
        i  = i;
        cout << i << endl;
    }while (i > 0);

    cout << c << endl;
    return 0;
}

Olay şu:Tamsayı taşması imzalanmış teknik olarak tanımlanmamış bir davranış. Ama x 86 GCC tamsayı aritmetik taşma üzerinde şal olan 86 tamsayı talimatları kullanarak uygular.

Bu nedenle, taşma sarmak için beklerdim tanımlanmayan bir davranış olmasına rağmen. Ama bu açıkça böyle değil. Ne kaçırdım?

Bu kullanarak derlenmiÅŸ:

~/Desktop$ g   main.cpp -O2

GCC Çıktı:

~/Desktop$ ./a.out
536870912
1073741824
-2147483648
0
0
0

... (infinite loop)

En iyi duruma getirme devre dışı, sonsuz döngü diye bir şey yok ve bu çıktı doğru mu? Visual Studio da doğru bu derler ve aşağıdaki sonucu verir:

Doğru Çıktı:

~/Desktop$ g   main.cpp
~/Desktop$ ./a.out
536870912
1073741824
-2147483648
3

İşte bazı diğer varyasyonları:

i *= 2;   //  Also fails and goes into infinite loop.
i <<= 1;  //  This seems okay. It does not enter infinite loop.

İşte tüm ilgili sürüm bilgileri:

~/Desktop$ g   -v
Using built-in specs.
COLLECT_GCC=g  
COLLECT_LTO_WRAPPER=/usr/lib/x86_64-linux-gnu/gcc/x86_64-linux-gnu/4.5.2/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ..

...

Thread model: posix
gcc version 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4) 
~/Desktop$ 

Şimdi soru şu:Bu GCC böcek mi? Ya ben tamsayı aritmetik nasıl işlediği hakkında bir şey yanlış mı?

Bu hata, C. (henüz teyit etmedim.) yeniden varsayıyorum çünkü bu C de etiketleme, ben *

DÃœZENLEME:

Burada döngü birleştirme: eğer düzgün tanıdım

.L5:
addl    ëp, ëp
movl    $_ZSt4cout, íi
movl    ëp, %esi
.cfi_offset 3, -40
call    _ZNSolsEi
movq    %rax, %rbx
movq    (%rax), %rax
movq    -24(%rax), %rax
movq    240(%rbx,%rax), %r13
testq   %r13, %r13
je  .L10
cmpb    $0, 56(%r13)
je  .L3
movzbl  67(%r13), êx
.L4:
movsbl  %al, %esi
movq    %rbx, %rdi
addl    $1, %r12d
call    _ZNSo3putEc
movq    %rax, %rdi
call    _ZNSo5flushEv
cmpl    $3, %r12d
jne .L5

CEVAP
7 EKÄ°M 2011, Cuma


Standart tanımsız davranış olduğunu söylüyorbunu demek. Her şey olabilir. "Hiçbir şey" "genellikle tamsayılar etrafında sarın, ama arada tuhaf şeyler olur".

Evet, 86 CPU, tam sayılargenelliklebeklediğiniz gibi sarın. This is one of those exceptions. derleyici tanımsız davranışa neden olmaz, ve uzak döngü sınaması optimize varsayar. Eğer gerçekten saran istiyorsanız, derleme g gcc -fwrapv pas; bu, iyi tanımlanmış (ikişer-tamamlayıcı) taşma semantik verir, ama performans zarar verebilir.

Bunu PaylaÅŸ:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VÄ°DEO

Rastgele Yazarlar

  • Hak5

    Hak5

    7 EYLÃœL 2005
  • LounaTutorials

    LounaTutoria

    10 EYLÃœL 2009
  • placeboing

    placeboing

    7 Mart 2006