public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/50986] New: weak static data members with constant initializers emitted in .rodata, leading to segfault on startup
@ 2011-11-03 18:40 richard-gccbugzilla at metafoo dot co.uk
  2012-02-01 19:59 ` [Bug c++/50986] " pinskia at gcc dot gnu.org
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: richard-gccbugzilla at metafoo dot co.uk @ 2011-11-03 18:40 UTC (permalink / raw)
  To: gcc-bugs

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: unassigned@gcc.gnu.org
        ReportedBy: richard-gccbugzilla@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.


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-12-25  3:49 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-11-03 18:40 [Bug c++/50986] New: weak static data members with constant initializers emitted in .rodata, leading to segfault on startup richard-gccbugzilla at metafoo dot co.uk
2012-02-01 19:59 ` [Bug c++/50986] " pinskia at gcc dot gnu.org
2012-02-01 21:15 ` richard-gccbugzilla at metafoo dot co.uk
2014-10-23 13:13 ` rafael.espindola at gmail dot com
2021-12-25  3:49 ` pinskia at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).