I have stumbled upon a problem that, I believe, can be attributed to a bug in GCC. The following source code can be used to reproduce the problem: int foo(void) { char * str = "test"; str[1] = 'a'; return 0; } int main() { foo(); return 0; } On a Solaris 10 system, I can compile and execute this code successfully using the following compiler: # /usr/bin/cc -V cc: Sun C 5.9 SunOS_i386 Patch 124868-01 2007/07/12 usage: cc [ options] files. Use 'cc -flags' for details If I try to do the same with GCC on my linux box, I get a segmentation fault on str[1] = 'a'. Here are the details: $ gcc -v -save-temps tst.c Using built-in specs. Target: i486-linux-gnu Configured with: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c ++,treelang --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/l ib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-inc lude-dir=/usr/include/c++/4.2 --program-suffix=-4.2 --enable-clocale=gnu --enabl e-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-targets=all --enable-c hecking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux -gnu Thread model: posix gcc version 4.2.4 (Ubuntu 4.2.4-1ubuntu4) /usr/lib/gcc/i486-linux-gnu/4.2.4/cc1 -E -quiet -v tst.c -mtune=generic -fpch-p reprocess -o tst.i ignoring nonexistent directory "/usr/local/include/i486-linux-gnu" ignoring nonexistent directory "/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../i4 86-linux-gnu/include" ignoring nonexistent directory "/usr/include/i486-linux-gnu" #include "..." search starts here: #include <...> search starts here: /usr/local/include /usr/lib/gcc/i486-linux-gnu/4.2.4/include /usr/include End of search list. /usr/lib/gcc/i486-linux-gnu/4.2.4/cc1 -fpreprocessed tst.i -quiet -dumpbase tst .c -mtune=generic -auxbase tst -version -fstack-protector -fstack-protector -o t st.s GNU C version 4.2.4 (Ubuntu 4.2.4-1ubuntu4) (i486-linux-gnu) compiled by GNU C version 4.2.4 (Ubuntu 4.2.4-1ubuntu4). GGC heuristics: --param ggc-min-expand=64 --param ggc-min-heapsize=64446 Compiler executable checksum: cbbe762aad92f3ea8e83d46e5489fd3e as --traditional-format -V -Qy -o tst.o tst.s GNU assembler version 2.18.0 (i486-linux-gnu) using BFD version (GNU Binutils fo r Ubuntu) 2.18.0.20080103 /usr/lib/gcc/i486-linux-gnu/4.2.4/collect2 --eh-frame-hdr -m elf_i386 --hash-st yle=both -dynamic-linker /lib/ld-linux.so.2 /usr/lib/gcc/i486-linux-gnu/4.2.4/.. /../../../lib/crt1.o /usr/lib/gcc/i486-linux-gnu/4.2.4/../../../../lib/crti.o /u sr/lib/gcc/i486-linux-gnu/4.2.4/crtbegin.o -L/usr/lib/gcc/i486-linux-gnu/4.2.4 - L/usr/lib/gcc/i486-linux-gnu/4.2.4 -L/usr/lib/gcc/i486-linux-gnu/4.2.4/../../../ ../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/i486-linux-gnu/4.2.4/../.. /.. tst.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/i486-linux-gnu/4.2.4/crtend.o /usr/lib/gcc/i486-lin ux-gnu/4.2.4/../../../../lib/crtn.o $ ./a.out Segmentation fault Interestingly enough, if I declare str as : char str[] = "test"; rather than: char * str = "test"; the code will compile and execute properly. I tried using -Wall and -pedantic to check whether GCC would produce any warnings but that does not seem to be the case. I got the same results with another version of GCC as well. Here are the details: $ gcc -v -save-temps tst.c Reading specs from /usr/lib/gcc-lib/i486-slackware-linux/3.3.6/specs Configured with: ../gcc-3.3.6/configure --prefix=/usr --enable-shared --enable-t hreads=posix --enable-__cxa_atexit --disable-checking --with-gnu-ld --verbose -- target=i486-slackware-linux --host=i486-slackware-linux Thread model: posix gcc version 3.3.6 /usr/lib/gcc-lib/i486-slackware-linux/3.3.6/cc1 -E -quiet -v -D__GNUC__=3 -D__G NUC_MINOR__=3 -D__GNUC_PATCHLEVEL__=6 tst.c tst.i ignoring nonexistent directory "/usr/i486-slackware-linux/include" #include "..." search starts here: #include <...> search starts here: /usr/local/include /usr/lib/gcc-lib/i486-slackware-linux/3.3.6/include /usr/include End of search list. /usr/lib/gcc-lib/i486-slackware-linux/3.3.6/cc1 -fpreprocessed tst.i -quiet -du mpbase tst.c -auxbase tst -version -o tst.s GNU C version 3.3.6 (i486-slackware-linux) compiled by GNU C version 3.3.6. GGC heuristics: --param ggc-min-expand=90 --param ggc-min-heapsize=113245 /usr/lib/gcc-lib/i486-slackware-linux/3.3.6/../../../../i486-slackware-linux/bi n/as -V -Qy -o tst.o tst.s GNU assembler version 2.15.92.0.2 (i486-slackware-linux) using BFD version 2.15. 92.0.2 20040927 /usr/lib/gcc-lib/i486-slackware-linux/3.3.6/collect2 --eh-frame-hdr -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 /usr/lib/gcc-lib/i486-slackware-linux/3.3.6/ ../../../crt1.o /usr/lib/gcc-lib/i486-slackware-linux/3.3.6/../../../crti.o /usr /lib/gcc-lib/i486-slackware-linux/3.3.6/crtbegin.o -L/usr/lib/gcc-lib/i486-slack ware-linux/3.3.6 -L/usr/lib/gcc-lib/i486-slackware-linux/3.3.6/../../../../i486- slackware-linux/lib -L/usr/lib/gcc-lib/i486-slackware-linux/3.3.6/../../.. tst.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as- needed /usr/lib/gcc-lib/i486-slackware-linux/3.3.6/crtend.o /usr/lib/gcc-lib/i48 6-slackware-linux/3.3.6/../../../crtn.o $ ./a.out Segmentation fault Any ideas? Cheers, Iran Rocha
Your code is clearly invalid: str points to "test", but that memory itself is read-only, roughly speaking. More correctly, the Standard says that the effect of attempting to modify a string literal is undefined, ie, *anything* can happen.
Thank you for the clarification. My friend and I ran across this while comparing the assembly generated by different compilers/platforms when manipulating strings. A largely academic exercise. That piece of code did not look right to me at first but what threw us off is the fact that the code worked with the Sun compiler and that -Wall -pedantic on gcc did not give us any warnings. We were puzzled by it. You are correct though. I checked the standard and it does specify that the result of such operation is undefined, which explains why it may work with some compilers but certainly something that shouldn't be relied on. Thanks again