c++ - Why does this loop produce "warning: iteration 3u invokes undefined behavior" and output more than 4 lines? -
c++ - Why does this loop produce "warning: iteration 3u invokes undefined behavior" and output more than 4 lines? -
compiling this:
#include <iostream> int main() { (int = 0; < 4; ++i) std::cout << i*1000000000 << std::endl; }
and gcc
produces next warning:
warning: iteration 3u invokes undefined behavior [-waggressive-loop-optimizations] std::cout << i*1000000000 << std::endl; ^
i understand there signed integer overflow.
what cannot why i
value broken overflow operation?
i've read answers why integer overflow on x86 gcc cause infinite loop?, i'm still not clear on why happens - "undefined" means "anything can happen", what's underlying cause of this specific behavior?
online: http://ideone.com/dmrrkr
compiler: gcc (4.8)
signed integer overflow (as strictly speaking, there no such thing "unsigned integer overflow") means undefined behaviour. , means can happen, , discussing why happen under rules of c++ doesn't create sense.
c++11 draft n3337: §5.4:1
if during evaluation of expression, result not mathematically defined or not in range of representable values type, behavior undefined. [ note: existing implementations of c++ ignore integer overflows. treatment of partition zero, forming remainder using 0 divisor, , floating point exceptions vary among machines, , adjustable library function. —end note ]
your code compiled g++ -o3
emits warning (even without -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 (int = 0; < 4; ++i) ^
the way can analyze programme doing, reading generated assembly code.
here total assembly listing:
.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 phone call ___main l4: movl %edi, (%esp) movl $__zst4cout, %ecx phone 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 phone call __znso3putec subl $4, %esp movl %eax, %ecx phone call __znso5flushev jmp l4 .p2align 4,,10 l5: movl %ebx, %ecx phone 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 phone call *%edx movsbl %al, %eax pushl %edx jmp l6 l15: phone 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 phone call __znst8ios_base4initc1ev movl $___tcf_0, (%esp) phone 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 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
i can barely read assembly, can see addl $1000000000, %edi
line. resulting code looks more like
for(int = 0; /* nothing, - infinite loop */; += 1000000000) std::cout << << std::endl;
this comment of @t.c.:
i suspect it's like: (1) because every iteration i
of value larger 2 has undefined behavior -> (2) can assume i <= 2
optimization purposes -> (3) loop status true -> (4) it's optimized away infinite loop.
gave me thought compare assembly code of op's code assembly code of next code, no undefined behaviour.
#include <iostream> int main() { // changed termination status (int = 0; < 3; ++i) std::cout << i*1000000000 << std::endl; }
and, in fact, right code has termination condition.
; ...snip... l6: mov ecx, edi mov dword ptr [esp], eax add together esi, 1000000000 phone call __znso3putec sub esp, 4 mov ecx, eax phone call __znso5flushev cmp esi, -1294967296 // here jne l7 lea esp, [ebp-16] xor eax, eax pop ecx ; ...snip...
omg, that's not obvious! it's not fair! demand trial fire!
deal it, wrote buggy code , should sense bad. bear consequences.
...or, alternatively, create proper utilize of improve diagnostics , improve debugging tools - that's for:
enable warnings
-wall
gcc alternative enables useful warnings no false positives. bare minimum should use. gcc has many other warning options, however, not enabled -wall
may warn on false positives visual c++ unfortunately lagging behind ability give useful warnings. @ to the lowest degree ide enables default. use debug flags debugging
for integer overflow-ftrapv
traps programme on overflow, clang compiler first-class this: -fcatch-undefined-behavior
catches lot of instances of undefined behaviour (note: "a lot of" != "all of them"
) i have spaghetti mess of programme not written me needs shipped tomorrow! help!!!!!!111oneone
use gcc's -fwrapv
this alternative instructs compiler assume signed arithmetic overflow of addition, subtraction , multiplication wraps around using twos-complement representation.
1 - rule not apply "unsigned integer overflow", §3.9.1.4 says that
unsigned integers, declared unsigned, shall obey laws of arithmetic modulo 2n n number of bits in value representation of particular size of integer.
and e.g. result of uint_max + 1
mathematically defined - rules of arithmetic modulo 2n
c++ gcc undefined-behavior
Comments
Post a Comment