निम्न कोड GCC पर एक अनंत लूप में जाता है:
#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;
}
तो यहाँ सौदा है: हस्ताक्षरित पूर्णांक अतिप्रवाह तकनीकी रूप से अपरिभाषित व्यवहार है। लेकिन x86 पूर्णांक निर्देशों का उपयोग करके x86 के जीसीसी पूर्णांक अंकगणित पर जीसीसी - जो अतिप्रवाह पर लपेटता है।
इसलिए, मैंने उम्मीद की होगी कि यह अतिप्रवाह पर लिपटा रहेगा - इस तथ्य के बावजूद कि यह अपरिभाषित व्यवहार है। लेकिन यह स्पष्ट रूप से ऐसा नहीं है। तो, मैंने क्या खोया?
मैंने इसका उपयोग करके संकलित किया:
~/Desktop$ g++ main.cpp -O2
GCC आउटपुट:
~/Desktop$ ./a.out
536870912
1073741824
-2147483648
0
0
0
... (infinite loop)
ऑप्टिमाइज़ेशन अक्षम होने के साथ, कोई अनंत लूप नहीं है और आउटपुट सही है। विजुअल स्टूडियो भी इसे सही ढंग से संकलित करता है और निम्न परिणाम देता है:
सही आउटपुट:
~/Desktop$ g++ main.cpp
~/Desktop$ ./a.out
536870912
1073741824
-2147483648
3
यहाँ कुछ अन्य विविधताएँ हैं:
i *= 2; // Also fails and goes into infinite loop.
i <<= 1; // This seems okay. It does not enter infinite loop.
यहां सभी प्रासंगिक संस्करण जानकारी दी गई है:
~/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$
तो सवाल यह है कि क्या यह जीसीसी में बग है? या मुझे कुछ गलत समझ में आया कि जीसीसी पूर्णांक अंकगणित को कैसे संभालता है?
* मैं इस सी को भी टैग कर रहा हूं, क्योंकि मुझे लगता है कि यह बग सी में पुन: उत्पन्न होगा (मैंने अभी तक इसे सत्यापित नहीं किया है।)
संपादित करें:
यहाँ लूप की असेंबली है: (यदि मैंने इसे ठीक से पहचाना है)
.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
।