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

Popular posts from this blog

php - Android app custom user registration and login with cookie using facebook sdk -

django - Access session in user model .save() -

php - .htaccess Multiple Rewrite Rules / Prioritizing -