http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50986
Bug #: 50986 Summary: weak static data members with constant initializers emitted in .rodata, leading to segfault on startup Classification: Unclassified Product: gcc Version: 4.6.3 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: richard-gccbugzi...@metafoo.co.uk It's possible for a weak variable K (either a static data member of a class template or a static variable in an inline function) to have a constant initializer in one translation unit (call it TU1) and a non-constant initializer in another translation unit (call it TU2), without an ODR violation. This can happen, for instance, if the initializer for an extern const int X whose value is used in K's initializer is visible in one TU but not the other. In this case, in TU1, g++ uses static initialization and puts the variable in .rodata. In TU2, it uses dynamic initialization. If these TUs are linked together in the wrong order, the linker will put the variable in .rodata but the binary will still try to dynamically initialize it. This causes the program to segfault on startup (trying to write to read-only memory). Testcase: $ cat repro.cpp struct S { static const int x; }; template<typename T> struct U { static const int k; }; #ifdef TU1 const int S::x = 42; #endif template<typename T> const int U<T>::k = T::x; #ifdef TU1 extern const int *f(); const int *g() { return &U<S>::k; } int main() { return *f() + U<S>::k; } #endif #ifdef TU2 const int *f() { return &U<S>::k; } #endif $ g++ repro.cpp -DTU1 -c -o tu1.o $ g++ repro.cpp -DTU2 -c -o tu2.o $ g++ tu1.o tu2.o $ ./a.out Segmentation fault clang has the same issue (which is how this was discovered), and the current proposed solution there is to never put weak constants in .rodata.