पूर्णांक ओवरफ़्लो पर हस्ताक्षर किए गए (कड़ाई से बोलते हुए, "अहस्ताक्षरित पूर्णांक ओवरफ़्लो" जैसी कोई चीज़ नहीं है) का अर्थ अपरिभाषित व्यवहार है । और इसका मतलब यह है कि कुछ भी हो सकता है, और सी ++ के नियमों के तहत ऐसा होने पर चर्चा करने का कोई मतलब नहीं है।
C ++ 11 ड्राफ्ट N3337: .45.4: 1
यदि किसी अभिव्यक्ति के मूल्यांकन के दौरान, परिणाम गणितीय रूप से not ned नहीं है या उसके प्रकार के लिए प्रतिनिधित्व योग्य मूल्यों की सीमा में नहीं है, तो व्यवहार unde ned है। [नोट: C ++ के अधिकांश मौजूदा कार्यान्वयन। Ows पर पूर्णांक को अनदेखा करते हैं। शून्य से विभाजन का उपचार, एक शून्य विभाजक का उपयोग करके शेष बना रहा है, और सभी point ओटिंग बिंदु अपवाद मशीनों के बीच भिन्न होते हैं, और आमतौर पर एक पुस्तकालय फ़ंक्शन द्वारा समायोज्य होता है। ध्यान दें]
आपका कोड g++ -O3
चेतावनी के साथ संकलित है (बिना भी -Wall
)
a.cpp: In function 'int main()':
a.cpp:11:18: warning: iteration 3u invokes undefined behavior [-Waggressive-loop-optimizations]
std::cout << i*1000000000 << std::endl;
^
a.cpp:9:2: note: containing loop
for (int i = 0; i < 4; ++i)
^
एकमात्र तरीका हम यह विश्लेषण कर सकते हैं कि कार्यक्रम क्या कर रहा है, उत्पन्न विधानसभा कोड को पढ़कर।
यहाँ पूर्ण विधानसभा सूची है:
.file "a.cpp"
.section .text$_ZNKSt5ctypeIcE8do_widenEc,"x"
.linkonce discard
.align 2
LCOLDB0:
LHOTB0:
.align 2
.p2align 4,,15
.globl __ZNKSt5ctypeIcE8do_widenEc
.def __ZNKSt5ctypeIcE8do_widenEc; .scl 2; .type 32; .endef
__ZNKSt5ctypeIcE8do_widenEc:
LFB860:
.cfi_startproc
movzbl 4(%esp), %eax
ret $4
.cfi_endproc
LFE860:
LCOLDE0:
LHOTE0:
.section .text.unlikely,"x"
LCOLDB1:
.text
LHOTB1:
.p2align 4,,15
.def ___tcf_0; .scl 3; .type 32; .endef
___tcf_0:
LFB1091:
.cfi_startproc
movl $__ZStL8__ioinit, %ecx
jmp __ZNSt8ios_base4InitD1Ev
.cfi_endproc
LFE1091:
.section .text.unlikely,"x"
LCOLDE1:
.text
LHOTE1:
.def ___main; .scl 2; .type 32; .endef
.section .text.unlikely,"x"
LCOLDB2:
.section .text.startup,"x"
LHOTB2:
.p2align 4,,15
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
LFB1084:
.cfi_startproc
leal 4(%esp), %ecx
.cfi_def_cfa 1, 0
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
.cfi_escape 0x10,0x5,0x2,0x75,0
movl %esp, %ebp
pushl %edi
pushl %esi
pushl %ebx
pushl %ecx
.cfi_escape 0xf,0x3,0x75,0x70,0x6
.cfi_escape 0x10,0x7,0x2,0x75,0x7c
.cfi_escape 0x10,0x6,0x2,0x75,0x78
.cfi_escape 0x10,0x3,0x2,0x75,0x74
xorl %edi, %edi
subl $24, %esp
call ___main
L4:
movl %edi, (%esp)
movl $__ZSt4cout, %ecx
call __ZNSolsEi
movl %eax, %esi
movl (%eax), %eax
subl $4, %esp
movl -12(%eax), %eax
movl 124(%esi,%eax), %ebx
testl %ebx, %ebx
je L15
cmpb $0, 28(%ebx)
je L5
movsbl 39(%ebx), %eax
L6:
movl %esi, %ecx
movl %eax, (%esp)
addl $1000000000, %edi
call __ZNSo3putEc
subl $4, %esp
movl %eax, %ecx
call __ZNSo5flushEv
jmp L4
.p2align 4,,10
L5:
movl %ebx, %ecx
call __ZNKSt5ctypeIcE13_M_widen_initEv
movl (%ebx), %eax
movl 24(%eax), %edx
movl $10, %eax
cmpl $__ZNKSt5ctypeIcE8do_widenEc, %edx
je L6
movl $10, (%esp)
movl %ebx, %ecx
call *%edx
movsbl %al, %eax
pushl %edx
jmp L6
L15:
call __ZSt16__throw_bad_castv
.cfi_endproc
LFE1084:
.section .text.unlikely,"x"
LCOLDE2:
.section .text.startup,"x"
LHOTE2:
.section .text.unlikely,"x"
LCOLDB3:
.section .text.startup,"x"
LHOTB3:
.p2align 4,,15
.def __GLOBAL__sub_I_main; .scl 3; .type 32; .endef
__GLOBAL__sub_I_main:
LFB1092:
.cfi_startproc
subl $28, %esp
.cfi_def_cfa_offset 32
movl $__ZStL8__ioinit, %ecx
call __ZNSt8ios_base4InitC1Ev
movl $___tcf_0, (%esp)
call _atexit
addl $28, %esp
.cfi_def_cfa_offset 4
ret
.cfi_endproc
LFE1092:
.section .text.unlikely,"x"
LCOLDE3:
.section .text.startup,"x"
LHOTE3:
.section .ctors,"w"
.align 4
.long __GLOBAL__sub_I_main
.lcomm __ZStL8__ioinit,1,1
.ident "GCC: (i686-posix-dwarf-rev1, Built by MinGW-W64 project) 4.9.0"
.def __ZNSt8ios_base4InitD1Ev; .scl 2; .type 32; .endef
.def __ZNSolsEi; .scl 2; .type 32; .endef
.def __ZNSo3putEc; .scl 2; .type 32; .endef
.def __ZNSo5flushEv; .scl 2; .type 32; .endef
.def __ZNKSt5ctypeIcE13_M_widen_initEv; .scl 2; .type 32; .endef
.def __ZSt16__throw_bad_castv; .scl 2; .type 32; .endef
.def __ZNSt8ios_base4InitC1Ev; .scl 2; .type 32; .endef
.def _atexit; .scl 2; .type 32; .endef
मैं मुश्किल से विधानसभा भी पढ़ सकता हूं, लेकिन यहां तक कि मैं addl $1000000000, %edi
रेखा भी देख सकता हूं । परिणामस्वरूप कोड अधिक दिखता है
for(int i = 0; /* nothing, that is - infinite loop */; i += 1000000000)
std::cout << i << std::endl;
@TC की यह टिप्पणी:
मुझे संदेह है कि यह कुछ ऐसा है: (1) क्योंकि i
2 से बड़े किसी भी मूल्य वाले प्रत्येक पुनरावृत्ति में अपरिभाषित व्यवहार होता है -> (2) हम यह मान सकते हैं कि i <= 2
अनुकूलन उद्देश्यों के लिए -> (3) लूप की स्थिति हमेशा सही होती है -> (4) ) यह एक अनंत लूप में दूर अनुकूलित है।
मुझे बिना किसी अपरिभाषित व्यवहार के, ओपी कोड के विधानसभा कोड की तुलना निम्नलिखित कोड के विधानसभा कोड से करने का विचार दिया।
#include <iostream>
int main()
{
// changed the termination condition
for (int i = 0; i < 3; ++i)
std::cout << i*1000000000 << std::endl;
}
और, वास्तव में, सही कोड में समाप्ति की स्थिति है।
; ...snip...
L6:
mov ecx, edi
mov DWORD PTR [esp], eax
add esi, 1000000000
call __ZNSo3putEc
sub esp, 4
mov ecx, eax
call __ZNSo5flushEv
cmp esi, -1294967296 // here it is
jne L7
lea esp, [ebp-16]
xor eax, eax
pop ecx
; ...snip...
OMG, यह पूरी तरह से स्पष्ट नहीं है! यह सही नहीं है! मैं आग से परीक्षण की मांग करता हूं!
इससे निपटने के लिए, आपने छोटी गाड़ी कोड लिखा है और आपको बुरा महसूस करना चाहिए। परिणाम भुगतना।
... या, वैकल्पिक रूप से, बेहतर डायग्नोस्टिक्स और बेहतर डिबगिंग टूल का उचित उपयोग करें - यही उनके लिए है:
मेरे पास मेरे द्वारा नहीं लिखे गए एक प्रोग्राम की स्पैगेटी मेस है जिसे कल भेजने की आवश्यकता है! मदद !!!!!! 111oneone
Gcc का प्रयोग करें -fwrapv
यह विकल्प कंपाइलर को यह मानने का निर्देश देता है कि जुड़वा-पूरक प्रतिनिधित्व का उपयोग करते हुए इसके अलावा, घटाव और गुणा गुणा पर हस्ताक्षर किए गए अंकगणित ओवरफ्लो करते हैं।
1 - यह नियम "अहस्ताक्षरित पूर्णांक ओवरफ़्लो" पर लागू नहीं होता है, जैसा कि .13.9.1.4 कहता है
अहस्ताक्षरित पूर्णांक, जिन्हें अहस्ताक्षरित घोषित किया गया है, अंकगणितीय मोडुलो 2 एन के नियमों का पालन करेंगे जहां एन पूर्णांक के उस विशेष आकार के मूल्य प्रतिनिधित्व में बिट्स की संख्या है।
और उदाहरण के लिए परिणाम UINT_MAX + 1
गणितीय रूप से परिभाषित किया गया है - अंकगणितीय मोडुलो 2 एन के नियमों द्वारा