Aşağıdaki kod, GCC'de sonsuz bir döngüye girer:
#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;
}
İşte anlaşma şu: İşaretli tamsayı taşması teknik olarak tanımlanmamış bir davranıştır. Ancak x86 üzerindeki GCC, taşma durumunda saran x86 tamsayı talimatlarını kullanarak tamsayı aritmetiği uygular.
Bu nedenle, tanımlanmamış bir davranış olmasına rağmen, taşmayı tamamlamasını bekliyordum. Ancak durum açıkça bu değil. Yani, ne kaçırdım?
Bunu kullanarak derledim:
~/Desktop$ g++ main.cpp -O2
GCC Çıkışı:
~/Desktop$ ./a.out
536870912
1073741824
-2147483648
0
0
0
... (infinite loop)
Optimizasyonlar devre dışı bırakıldığında, sonsuz döngü yoktur ve çıktı doğrudur. Visual Studio ayrıca bunu doğru bir şekilde derler ve aşağıdaki sonucu verir:
Doğru Çıktı:
~/Desktop$ g++ main.cpp
~/Desktop$ ./a.out
536870912
1073741824
-2147483648
3
İşte diğer bazı 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$
Yani soru şu: Bu GCC'de bir hata mı? Veya GCC'nin tamsayı aritmetiğini nasıl işlediğiyle ilgili bir şeyi yanlış mı anladım?
* Bu C'yi de etiketliyorum, çünkü bu hatanın C'de çoğalacağını varsayıyorum (henüz doğrulamadım.)
DÜZENLE:
Döngünün montajı şu şekildedir: (eğer doğru bir şekilde tanıyorsam)
.L5:
addl %ebp, %ebp
movl $_ZSt4cout, %edi
movl %ebp, %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), %eax
.L4:
movsbl %al, %esi
movq %rbx, %rdi
addl $1, %r12d
call _ZNSo3putEc
movq %rax, %rdi
call _ZNSo5flushEv
cmpl $3, %r12d
jne .L5
gcc -S
.