Bug 52477

Summary: Wrong initialization order? __attribute__((constructor)) vs static data access
Product: gcc Reporter: Przemysław Pawełczyk <przemoc>
Component: c++Assignee: Not yet assigned to anyone <unassigned>
Status: NEW ---    
Severity: major CC: jason, marxin, msebor, pawel_sikora, ro, webrown.cpp
Priority: P3    
Version: 4.7.0   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2017-03-16 00:00:00
Attachments: Short exemplary code showing the problem

Description Przemysław Pawełczyk 2012-03-04 12:50:09 UTC
Created attachment 26821 [details]
Short exemplary code showing the problem

Attached file compiles flawlessly on 4.7.0, but the output binary segfaults. Works fine in 4.6.2 though (as expected).

Looks like a serious regression.

g++-4.7 (GCC) 4.7.0 20120304 (prerelease)
built on debian wheezy x64 with:
--enable-languages=c,c++ --prefix=/opt/gcc-4.7 --program-suffix=-4.7

svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_7-branch@184878
Comment 1 Pawel Sikora 2012-03-04 13:54:09 UTC
looks like .init_array vs. .ctors problem.
Comment 2 Pawel Sikora 2012-03-04 14:16:29 UTC
you should specify explicit initialization order to avoid gpf, e.g.:

static std::map<int, int> m __attribute__((init_priority(101)));
static void insert() __attribute__((constructor(102)));
Comment 3 Przemysław Pawełczyk 2012-03-04 14:24:10 UTC
Thanks for solution, but...

Isn't such order obvious or isn't it at least the most widely used one? I mean that by default static data initialization should precede constructor-functions, no? It worked in gcc 4.6 and is there any good reason to break it?
Comment 4 Richard Biener 2012-03-05 10:20:37 UTC
I think it's undefined what you relied upon.
Comment 5 Martin Sebor 2017-03-15 23:00:48 UTC
Resolving as invalid based on comment #3.  The manual does seem to suggest that this should work:

   "The priorities for constructor and destructor functions are the same as those specified for namespace-scope C++ objects (see C++ Attributes)."

Let me add a blurb to make clear that the order between C++ ctors and functions declared attribute constructor is unspecified.

Blurb posted for review:
https://gcc.gnu.org/ml/gcc-patches/2017-03/msg00863.html
Comment 6 Jason Merrill 2017-03-16 04:46:52 UTC
I don't think this is undefined; it seems natural for these functions to be ordered with a translation unit along with dynamic initialization of non-local variables.  So for

---
extern "C" int printf (const char *, ...);

struct A { A() { printf ("A\n"); } } a;

static void B() __attribute__((constructor));
static void B()
{
  printf ("B\n");
}

struct C { C() { printf ("C\n"); } } c;

int main() {}
---

I would expect A B C, and gcc currently outputs B A C.  Instead of emitting constructor functions directly into .init_array as we do now, we should remember them and call them from __static_initialization_and_destruction_0.

Note that 4.6 gave the differently wrong A C B, due to running .init_array in the opposite order, so this isn't really a regression.
Comment 7 Martin Sebor 2017-03-20 18:34:03 UTC
Author: msebor
Date: Mon Mar 20 18:33:31 2017
New Revision: 246288

URL: https://gcc.gnu.org/viewcvs?rev=246288&root=gcc&view=rev
Log:
PR c++/52477 - Wrong initialization order __attribute__((constructor)) vs static data access

* doc/extend.texi (attribute constructor): Document present limitation.

Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/doc/extend.texi
Comment 8 Martin Sebor 2017-03-20 18:35:47 UTC
r246288 updates the manual for GCC 7 and documents the limitation (as per commetn #6) but the issue itself remains unresolved.
Comment 9 Martin Liška 2017-08-10 19:12:49 UTC
*** Bug 81337 has been marked as a duplicate of this bug. ***
Comment 10 Martin Liška 2017-08-10 19:13:38 UTC
I will try to look at it.
Comment 11 Rainer Orth 2018-02-01 10:24:49 UTC
(In reply to Martin Liška from comment #10)
> I will try to look at it.

Do you see a chance to look at this before GCC 8?

Thanks.
  Rainer
Comment 12 Martin Liška 2018-02-13 08:24:48 UTC
(In reply to Rainer Orth from comment #11)
> (In reply to Martin Liška from comment #10)
> > I will try to look at it.
> 
> Do you see a chance to look at this before GCC 8?
> 
> Thanks.
>   Rainer

I'm sorry but probably after the release in next stage1.
Comment 13 Martin Liška 2018-08-16 10:31:26 UTC
Well, after we documented that can we simply close it?
Comment 14 Rainer Orth 2018-08-16 11:30:42 UTC
(In reply to Martin Liška from comment #13)
> Well, after we documented that can we simply close it?

Quite the contrary: that documents a *current* limitation!  See Jason's comment #6
for what needs to happen.
Comment 15 Martin Liška 2018-08-16 11:44:36 UTC
(In reply to Rainer Orth from comment #14)
> (In reply to Martin Liška from comment #13)
> > Well, after we documented that can we simply close it?
> 
> Quite the contrary: that documents a *current* limitation!  See Jason's
> comment #6
> for what needs to happen.

I see, thanks for clarification.
Comment 16 Martin Liška 2018-10-03 13:34:28 UTC
Leaving for now..