Hello GCC, I'm facing a wierd compiler optimization problem. Consider the code snippet below #include <stdio.h> int printChar(unsigned long cur_col, unsigned char c) { char buf[256]; char* bufp = buf; char cnt = sizeof(buf) - 2; /* overflow in implicit type conversion */ unsigned long terminal_width = 500; while ((cur_col++ < terminal_width) && cnt) { *bufp++ = c; cnt--; } *bufp++ = '\n'; *bufp = 0; printf("%c\n", buf[0]); return 1; } int main() { printChar(80, '-'); return 1; } While compiler optimization should guarantee that the result of execution is same at all optimization levels, I'm observing difference in the result of execution of the above program when optimized to different levels. Although there is fundamental problem with the statement "char cnt = sizeof(buf) - 2", GCC seems to be warning(that too only when -pedantic flag is used) about overflow error while silently discarding any code related to cnt i.e. the check "&& cnt" in the if-clause is silently discarded by the compiler at -O2. $]gcc -g char.c -o char.c.unoptimized -m32 -O0 -Wall -Wextra -pedantic char.c: In function ‘printChar’: char.c:8: warning: overflow in implicit constant conversion $]gcc -g char.c -o char.c.optimized -m32 -O2 -Wall -Wextra -pedantic char.c: In function ‘printChar’: char.c:8: warning: overflow in implicit constant conversion $]./char.c.unoptimized - $]./char.c.optimized - Segmentation fault (core dumped) Basically the crash here is because of elimination of the check in the if-clause "&& cnt" which is causing stack overrun and thereby SIGSEGV. While standards may say that the behaviour is undefined when an unsigned value is stored in a signed value, can a language lawyer explain to me why GCC chose to eliminate code pertaining to cnt considering it as dead-code ? Below is the objdump -S output of optimized and unoptimized binaries. A) Optimized Binary int printChar(unsigned long cur_col, unsigned char c) { 80483b0: 55 push %ebp 80483b1: 89 e5 mov %esp,%ebp 80483b3: 81 ec 08 01 00 00 sub $0x108,%esp 80483b9: 8b 45 08 mov 0x8(%ebp),%eax char buf[256]; char* bufp = buf; char cnt = sizeof(buf) - 2; unsigned long terminal_width = 500; while ((cur_col++ < terminal_width) && cnt) { 80483bc: 8d 8d 00 ff ff ff lea 0xffffff00(%ebp),%ecx 80483c2: 8b 55 0c mov 0xc(%ebp),%edx 80483c5: 3d f3 01 00 00 cmp $0x1f3,%eax 80483ca: 77 18 ja 80483e4 <printChar+0x34> 80483cc: 83 c0 01 add $0x1,%eax 80483cf: 8d 8d 00 ff ff ff lea 0xffffff00(%ebp),%ecx 80483d5: 83 c0 01 add $0x1,%eax *bufp++ = c; 80483d8: 88 11 mov %dl,(%ecx) 80483da: 83 c1 01 add $0x1,%ecx 80483dd: 3d f5 01 00 00 cmp $0x1f5,%eax 80483e2: 75 f1 jne 80483d5 <printChar+0x25> cnt--; } *bufp++ = '\n'; 80483e4: c6 01 0a movb $0xa,(%ecx) *bufp = 0; 80483e7: c6 41 01 00 movb $0x0,0x1(%ecx) printf("%c\n", buf[0]); 80483eb: 0f be 85 00 ff ff ff movsbl 0xffffff00(%ebp),%eax 80483f2: c7 04 24 20 85 04 08 movl $0x8048520,(%esp) 80483f9: 89 44 24 04 mov %eax,0x4(%esp) 80483fd: e8 b6 fe ff ff call 80482b8 <printf@plt> return 1; } 8048402: b8 01 00 00 00 mov $0x1,%eax 8048407: c9 leave 8048408: c3 ret 8048409: 8d b4 26 00 00 00 00 lea 0x0(%esi),%esi B) Unoptimized binary int printChar(unsigned long cur_col, unsigned char c) { 80483a4: 55 push %ebp 80483a5: 89 e5 mov %esp,%ebp 80483a7: 81 ec 28 01 00 00 sub $0x128,%esp 80483ad: 8b 45 0c mov 0xc(%ebp),%eax 80483b0: 88 85 ec fe ff ff mov %al,0xfffffeec(%ebp) char buf[256]; char* bufp = buf; 80483b6: 8d 85 f4 fe ff ff lea 0xfffffef4(%ebp),%eax 80483bc: 89 45 f4 mov %eax,0xfffffff4(%ebp) char cnt = sizeof(buf) - 2; 80483bf: c6 45 fb fe movb $0xfe,0xfffffffb(%ebp) unsigned long terminal_width = 500; 80483c3: c7 45 fc f4 01 00 00 movl $0x1f4,0xfffffffc(%ebp) while ((cur_col++ < terminal_width) && cnt) { 80483ca: eb 14 jmp 80483e0 <printChar+0x3c> *bufp++ = c; 80483cc: 0f b6 95 ec fe ff ff movzbl 0xfffffeec(%ebp),%edx 80483d3: 8b 45 f4 mov 0xfffffff4(%ebp),%eax 80483d6: 88 10 mov %dl,(%eax) 80483d8: 83 45 f4 01 addl $0x1,0xfffffff4(%ebp) cnt--; 80483dc: 80 6d fb 01 subb $0x1,0xfffffffb(%ebp) 80483e0: 8b 45 08 mov 0x8(%ebp),%eax 80483e3: 3b 45 fc cmp 0xfffffffc(%ebp),%eax 80483e6: 0f 92 c0 setb %al 80483e9: 83 45 08 01 addl $0x1,0x8(%ebp) 80483ed: 83 f0 01 xor $0x1,%eax 80483f0: 84 c0 test %al,%al 80483f2: 75 06 jne 80483fa <printChar+0x56> 80483f4: 80 7d fb 00 cmpb $0x0,0xfffffffb(%ebp) 80483f8: 75 d2 jne 80483cc <printChar+0x28> } *bufp++ = '\n'; 80483fa: 8b 45 f4 mov 0xfffffff4(%ebp),%eax 80483fd: c6 00 0a movb $0xa,(%eax) 8048400: 83 45 f4 01 addl $0x1,0xfffffff4(%ebp) *bufp = 0; 8048404: 8b 45 f4 mov 0xfffffff4(%ebp),%eax 8048407: c6 00 00 movb $0x0,(%eax) printf("%c\n", buf[0]); 804840a: 0f b6 85 f4 fe ff ff movzbl 0xfffffef4(%ebp),%eax 8048411: 0f be c0 movsbl %al,%eax 8048414: 89 44 24 04 mov %eax,0x4(%esp) 8048418: c7 04 24 30 85 04 08 movl $0x8048530,(%esp) 804841f: e8 94 fe ff ff call 80482b8 <printf@plt> return 1; 8048424: b8 01 00 00 00 mov $0x1,%eax } 8048429: c9 leave 804842a: c3 ret g++ -v Using built-in specs. Target: x86_64-redhat-linux Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --disable-plugin --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic --host=x86_64-redhat-linux Thread model: posix gcc version 4.1.2 20080704 (Red Hat 4.1.2-52)