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

* [Bug c++/50986] weak static data members with constant initializers emitted in .rodata, leading to segfault on startup
  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 ` pinskia at gcc dot gnu.org
  2012-02-01 21:15 ` richard-gccbugzilla at metafoo dot co.uk
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: pinskia at gcc dot gnu.org @ 2012-02-01 19:59 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50986

--- Comment #1 from Andrew Pinski <pinskia at gcc dot gnu.org> 2012-02-01 19:58:12 UTC ---
I think you are violating ODR here.


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

* [Bug c++/50986] weak static data members with constant initializers emitted in .rodata, leading to segfault on startup
  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
  3 siblings, 0 replies; 5+ messages in thread
From: richard-gccbugzilla at metafoo dot co.uk @ 2012-02-01 21:15 UTC (permalink / raw)
  To: gcc-bugs

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50986

--- Comment #2 from Richard Smith <richard-gccbugzilla at metafoo dot co.uk> 2012-02-01 21:14:35 UTC ---
As noted in comment#0, I believe there is no ODR violation here. Each
definition of U<S>::k consists of the same sequence of tokens, every name
refers to the same entity in both definitions, and none of the other provisions
of [basic.def.odr]p5 applies.

After some discussion, the proposed approach in clang is (roughly) to always
generate a guard variable (initialized to 1 for a statically-initialized
variable), and to put the variable and its guard variable in the same COMDAT
group. Full details are in this thread:

http://lists.cs.uiuc.edu/pipermail/cfe-dev/2011-November/018816.html


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

* [Bug c++/50986] weak static data members with constant initializers emitted in .rodata, leading to segfault on startup
  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
  3 siblings, 0 replies; 5+ messages in thread
From: rafael.espindola at gmail dot com @ 2014-10-23 13:13 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50986

--- Comment #3 from Rafael Avila de Espindola <rafael.espindola at gmail dot com> ---
In clang this was fixed by putting a .init_array section in the same comdat as
the variable it is initializing. That way if the variable is dropped, so is the
initialization code.


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

* [Bug c++/50986] weak static data members with constant initializers emitted in .rodata, leading to segfault on startup
  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
                   ` (2 preceding siblings ...)
  2014-10-23 13:13 ` rafael.espindola at gmail dot com
@ 2021-12-25  3:49 ` pinskia at gcc dot gnu.org
  3 siblings, 0 replies; 5+ messages in thread
From: pinskia at gcc dot gnu.org @ 2021-12-25  3:49 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50986

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |wrong-code

--- Comment #4 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
How clang fixes this is by putting the global initializer for U<S>::k (in TU2)
in the same comdat section as the non-readonly case.

^ 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).