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
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.
Hayır genişlik/yükseklik maddeleri aya...
Neden bu sonsuz bir döngüye girer ki?...
Neden imzasız taşma tanımlanan davranı...
Neden bu yöntem sonsuz bir döngüye ned...
Neden bazı yüzer < karşılaştırmalar...