Bug 44059 - [4.5 Regression] Static initializers executed more than once when using unique global symbols
Summary: [4.5 Regression] Static initializers executed more than once when using uniqu...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.5.0
: P3 major
Target Milestone: 4.5.1
Assignee: Jakub Jelinek
URL:
Keywords:
: 44815 (view as bug list)
Depends on:
Blocks:
 
Reported: 2010-05-10 13:37 UTC by Ivan Stankovic
Modified: 2010-07-24 18:39 UTC (History)
3 users (show)

See Also:
Host: i686-pc-linux-gnu
Target: i686-pc-linux-gnu
Build: i686-pc-linux-gnu
Known to work:
Known to fail:
Last reconfirmed: 2010-05-11 18:28:30


Attachments
The test case (759 bytes, application/x-bzip)
2010-05-10 13:40 UTC, Ivan Stankovic
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Ivan Stankovic 2010-05-10 13:37:48 UTC
With g++ 4.5.0 static initializers can be executed more than once.
Here's how. Let a.cc contain the following code:

#include <stdio.h>

struct A {
  A() {
    static int x = printf("x initialized at @%p\n", &x);
  }
};

extern "C" void inita();

void inita()
{
  A x;
  A y;
}

And let b.cc be the copy of a.cc where 'inita' has been renamed
to 'initb'. Then make a shared library a.so from a.cc and b.so from
b.cc. Finally, make a program that dynamically loads a.so and b.so
and calls inita and initb functions.

Since 'x' ends up as a unique global symbol, there will be only one
object in the process, but the initialization code will be run twice
(the address printed will be the same).
Comment 1 Ivan Stankovic 2010-05-10 13:40:39 UTC
Created attachment 20619 [details]
The test case

Just unpack and run 'make; make run'. The output
should be something like:

x initialized at @0x40021a28
x initialized at @0x40021a28

(note that the addresses are identical).
Comment 2 Richard Biener 2010-05-10 13:54:41 UTC
It works for me.  You need to build shared libraries with -fPIC.
Comment 3 Richard Biener 2010-05-10 13:57:46 UTC
Or rather as you use dlopen you need to use RTLD_GLOBAL.
Comment 4 Jakub Jelinek 2010-05-10 14:09:22 UTC
Re: #c2, that's just because you are using too old binutils I guess.

The bug seems to be in:
        .type _ZGVZN1AC1EvE1x, @object
        .type _ZZN1AC1EvE1x, @gnu_unique_object
I believe the guard needs to be @gnu_unique_object as well.
Comment 5 Ivan Stankovic 2010-05-10 14:14:47 UTC
Indeed, using RTLD_GLOBAL works around the problem. However, I don't think
one should just resort to using this flag with dlopen everywhere. The problem
was originally found with Python modules written in C, and while one can
change the dlopen flags used for Python imports, I'm not sure that that won't
break something else.

As Jakub has pointed out, the guard needs to be unique as well.
Comment 6 Jakub Jelinek 2010-05-10 14:39:01 UTC
I guess the problem is in the !DECL_ARTIFICIAL (DECL) test in ASM_DECLARE_OBJECT_NAME macro - the guard is artificial.
Not sure why that has been added.
      /* For template static data member instantiations or              \
         inline fn local statics, use gnu_unique_object so that         \
         they will be combined even under RTLD_LOCAL.  */               \
      if (USE_GNU_UNIQUE_OBJECT                                         \
          && !DECL_ARTIFICIAL (DECL) && DECL_ONE_ONLY (DECL))           \
        ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "gnu_unique_object");    \
      else                                                              \
        ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object");               \
Comment 7 Jakub Jelinek 2010-05-10 14:39:42 UTC
Reopening.
Comment 8 Jakub Jelinek 2010-05-11 18:14:48 UTC
Subject: Bug 44059

Author: jakub
Date: Tue May 11 18:14:19 2010
New Revision: 159287

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=159287
Log:
	PR c++/44059
	* config/elfos.h (ASM_DECLARE_OBJECT_NAME): Use qnu_unique_object
	even for DECL_ONE_ONLY DECL_ARTIFICIAL !TREE_READONLY decls.
	* config/alpha/elf.h (ASM_DECLARE_OBJECT_NAME): Likewise.
	* dwarf2asm.c (dw2_output_indirect_constant_1): Set TREE_READONLY
	on DW.ref.* decls.

Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/config/alpha/elf.h
    trunk/gcc/config/elfos.h
    trunk/gcc/dwarf2asm.c

Comment 9 Jakub Jelinek 2010-05-11 18:28:30 UTC
Fixed on the trunk so far, will backport to 4.5 after a while if there aren't any issues with it on the trunk.
Comment 10 Jakub Jelinek 2010-06-30 15:17:20 UTC
Subject: Bug 44059

Author: jakub
Date: Wed Jun 30 15:16:54 2010
New Revision: 161607

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=161607
Log:
	Backport from mainline
	2010-05-11  Jakub Jelinek  <jakub@redhat.com>

	PR c++/44059
	* config/elfos.h (ASM_DECLARE_OBJECT_NAME): Use qnu_unique_object
	even for DECL_ONE_ONLY DECL_ARTIFICIAL !TREE_READONLY decls.
	* config/alpha/elf.h (ASM_DECLARE_OBJECT_NAME): Likewise.
	* dwarf2asm.c (dw2_output_indirect_constant_1): Set TREE_READONLY
	on DW.ref.* decls.

Modified:
    branches/gcc-4_5-branch/gcc/ChangeLog
    branches/gcc-4_5-branch/gcc/config/alpha/elf.h
    branches/gcc-4_5-branch/gcc/config/elfos.h
    branches/gcc-4_5-branch/gcc/dwarf2asm.c
    branches/gcc-4_5-branch/gcc/testsuite/g++.dg/warn/Wconversion-null-2.C   (props changed)

Propchange: branches/gcc-4_5-branch/gcc/testsuite/g++.dg/warn/Wconversion-null-2.C
            ('svn:mergeinfo' removed)


Comment 11 Jakub Jelinek 2010-07-08 17:08:20 UTC
Fixed.
Comment 12 Andrew Pinski 2010-07-24 18:39:46 UTC
*** Bug 44815 has been marked as a duplicate of this bug. ***