Hi All, In a much larger application, I was getting a weird segfault that an assignment to a temporary variable fixed. I distilled the example into the attached "test_case.c". When I run test_case.c under valgrind I get a memory read error, and it segfaults with electric fence, but I'm not actually able to get a true segfault. However, I am pretty sure that the same issue was causing the segfault in my application.
>From my really limited assembly knowledge, it looks that on 64 bit machines gcc is trying to do a full 8 byte read into the register followed by a 2 byte shift ( instead of 4 then 2 byte read ). If the two extra bytes are out of bounds it will segfault. This explains why I get the sporadic segfaults in my bigger application ( where I can actually be at the page boundary ), but not in the test case. This only occurs on 64 bit machines, and my gcc version info is: nboley@ingvas:~/Desktop$ gcc -v Using built-in specs. Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.4.4-14ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.4 --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5) Best, Nathan Boley
#include <stdio.h> #include <stdlib.h> /* Does NOT cause memory error */ typedef struct __attribute__((__packed__)) { unsigned short chr; unsigned int loc; } GENOME_LOC_TYPE_2; /* Causes memory error */ typedef struct __attribute__((__packed__)) { unsigned chr :16; unsigned loc :32; } GENOME_LOC_TYPE; void print_mapped_location( GENOME_LOC_TYPE loc ) { printf( "%i\n", loc.loc ); } int main( int argc, char* argv ) { char* data; data = malloc(12*sizeof(char)); GENOME_LOC_TYPE* gen_array = (GENOME_LOC_TYPE*) data; gen_array[0].loc = 0; gen_array[1].loc = 1; /* Make sure the structure is actually 6 bytes */ printf("Gen Loc Type Size: %zu\n", sizeof(GENOME_LOC_TYPE) ); /* Works fine. */ printf( "%i\n", gen_array[1].loc ); /* Works fine */ GENOME_LOC_TYPE loc = gen_array[1]; print_mapped_location( loc ); /* Causes valgrind error */ /* Cause -lefence segfault */ print_mapped_location( gen_array[1] ); free( data ); }