gcc (GCC) 4.0.2 20050901 (prerelease) (SUSE Linux) SUSE Linux 10.0 i686 I don'know, if this is a gcc or elf bug. I use the following construct: Slib1 => Dlib1 Slib1 + Dlib1 => Dlib2 Test => dlopen/dlclose (Dlib2) Slib1 is a static lib. Dlib1 is a shared lib containing Slib1. Dlib2 is a shared lib containing Dlib1 and Slib1. After building the libraries with hidden visibility: tmp/demo/lib/linuxrelease> readelf -s -W -D libdlib1.so | c++filt ... 14 15: 00001a80 4 OBJECT GLOBAL DEFAULT 23 SLibC1::m_str ... tmp/demo/lib/linuxrelease> readelf -s -W -D libdlib2.so | c++filt ... 14 15: 00001ad8 4 OBJECT GLOBAL DEFAULT 23 SLibC1::m_str ... Both Dso-s will have the static member SLibC1::m_str with DEFAULT visibility. If you try to load / read symbol / close / load the Dso libdlib2.so, it will crash with the following error message: *** glibc detected *** double free or corruption (fasttop): 0x0804b888 *** If you set: export MALLOC_CHECK_=3 you can see in the debugger, that calling the global dtor in libdlib2.so at ~SLibC1::m_str() causes the crash. If you change hash_map to map in the example below (comment the line #define BUG 1), the test is OK. In this case the visibility of SLibC1::m_str is hidden. If this problem already known, does a workaround exist? I will supply the automake files. Without them I could not reproduce bug(?). I try to upload the whole configuration, but here are source files in the following tree: (how can I upload an attachment?) . |-- AUTHORS <= dummy |-- COPYING <= dummy |-- ChangeLog <= dummy |-- INSTALL <= dummy |-- NEWS <= dummy |-- README <= dummy |-- configure.ac |-- dlib1 | |-- dlib1_m1.cpp | `-- makefile.am |-- dlib2 | |-- dlib2_m1.cpp | `-- makefile.am |-- lib |-- makefile.am `-- stlib1 |-- makefile.am `-- stlib1_m1.cpp >>>>>>> stlib1_m1.cpp #include <string> #define BUG 1 #ifdef BUG #include <ext/hash_map> class SLibC1 : public __gnu_cxx::hash_map<int, int > #else #include <map> class SLibC1 : public std::map<int, int > #endif { public: static const std::string m_str; }; const std::string SLibC1::m_str = "SLibC1 1.0"; <<<<EOF>>>> >>>>>>> dlib1_m1.cpp struct __attribute__ ((visibility("default"))) Dlib1C1 { void Dlib1Func1() {} }; <<<<EOF>>>> >>>>>>> dlib2_m1.cpp struct __attribute__ ((visibility("default"))) Dlib2C1 { void Dlib2Func1() {}; }; <<<<EOF>>>> >>>>>>> configure.ac _dnl Process this file with autoconf to produce a configure script. AC_INIT([PSP],[pre]) AM_INIT_AUTOMAKE dnl Checks for programs. AC_PROG_LIBTOOL #AC_PROG_RANLIB AC_PROG_CXX AC_PROG_CPP AC_PROG_CC AC_LANG(C++) abs_top_srcdir=`pwd` VERSION_INFO="-avoid-version" AC_CONFIG_FILES([dlib1/makefile]) AC_CONFIG_FILES([dlib2/makefile]) AC_CONFIG_FILES([stlib1/makefile]) PRODNAME="linuxrelease" CXXFLAGS=" -fvisibility=hidden -fvisibility-inlines-hidden -D_Linux " CFLAGS=$CFLAGS" -fvisibility=hidden -D_Linux " ALD_FLAGS=" -no-undefined" SYSLIBS="-ldl" AM_CONFIG_HEADER([config.h]) AC_CONFIG_FILES([makefile]) dnl Checks for libraries. dnl Checks for header files. dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_C_INLINE AC_C_BIGENDIAN AC_TYPE_SIZE_T dnl Checks for library functions. AC_SUBST(abs_top_srcdir) AC_SUBST(PRODNAME) AC_SUBST(AINC_PATH) AC_SUBST(ALD_FLAGS) AC_SUBST(SYSLIBS) AC_SUBST(VERSION_INFO) AC_OUTPUT([]) <<<<EOF>>>> >>>>>>> ./makefile.am SUBDIRS = stlib1 dlib1 dlib2 exe <<<<EOF>>>> >>>>>>> stlib1/makefile.am libdir = ${abs_top_srcdir}/lib/@PRODNAME@ lib_LTLIBRARIES = libstlib1.la libstlib1_la_LDFLAGS = -all-static libstlib1_la_LIBADD = libstlib1_la_SOURCES = stlib1_m1.cpp libstlib1_la_CPPFLAGS = -D_LIB -I${top_srcdir}/inc @AINC_PATH@ install-exec-local: mkdir -p $(libdir)/.libs && \ sed -e "1s/libstlib1.la/libstlib1_noi.la/;s/^old_library=.*/old_library='..\/libstlib1.a'/;s/^installed=.*/installed=no/;s/^libdir=.*/libdir=''/" libstlib1.la >$(libdir)/libstlib1_noi.la <<<<EOF>>>> >>>>>>> dlib1/makefile.am libdir = ${abs_top_srcdir}/lib/@PRODNAME@ lib_LTLIBRARIES = libdlib1.la libdlib1_la_LDFLAGS = @VERSION_INFO@ @ALD_FLAGS@ -L${abs_top_srcdir}/lib/@PRODNAME@ libdlib1_la_SOURCES = dlib1_m1.cpp libdlib1_la_LIBADD = -lstlib1 @SYSLIBS@ libdlib1_la_CPPFLAGS = -D_USRDLL -DDLIB1_EXPORTS -I${top_srcdir}/stlib1 -I${top_srcdir}/inc @AINC_PATH@ install-exec-local: rm -f $(libdir)/libdlib1.a && \ touch $(libdir)/_x.o && \ ar cru $(libdir)/libdlib1.a $(libdir)/_x.o && \ ranlib $(libdir)/libdlib1.a && \ cp $(libdir)/libdlib1.a .libs/ && \ rm -f $(libdir)/_x.o <<<<EOF>>>> >>>>>>> dlib2/makefile.am libdir = ${abs_top_srcdir}/lib/@PRODNAME@ lib_LTLIBRARIES = libdlib2.la libdlib2_la_LDFLAGS = @VERSION_INFO@ @ALD_FLAGS@ -L${abs_top_srcdir}/lib/@PRODNAME@ libdlib2_la_SOURCES = dlib2_m1.cpp libdlib2_la_LIBADD = -ldlib1 -lstlib1 @SYSLIBS@ libdlib2_la_CPPFLAGS = -D_USRDLL -DDLIB2_EXPORTS -I${top_srcdir}/stlib1 -I${top_srcdir}/dlib1 -I${top_srcdir}/inc @AINC_PATH@ install-exec-local: rm -f $(libdir)/libdlib2.a && \ touch $(libdir)/_x.o && \ ar cru $(libdir)/libdlib2.a $(libdir)/_x.o && \ ranlib $(libdir)/libdlib2.a && \ cp $(libdir)/libdlib2.a .libs/ && \ rm -f $(libdir)/_x.o <<<<EOF>>>> Installation: go to the installation dir, and issue: libtoolize --force aclocal autoheader autoconf automake --add-missing --warning=portability --warning=obsolete ./configure make install cd lib/linuxrelease readelf -s -W -D libdlib1.so | c++filt
Created attachment 11113 [details] Automke sources to reproduce/test the visibility change of static members
Can you give some sources that don't use automake? Because it is hard to follow what is wrong in this bug.
Created attachment 11303 [details] Simple test without automake files to test visibility changes of static members To create the binaries and run the test: >tar -xzf simpletest.tar.gz >cd simpletest >./build.sh Actually the shared libs libdlib1.so and libdlib2.so should not export any symbols, but as you can see, both of them have the global symbol SLibC1::m_str. But only in case of hash_map. With std::map works.
(In reply to comment #2) > Can you give some sources that don't use automake? Because it is hard to > follow what is wrong in this bug. I have uploaded a simple test without automake files. Actually this bug (if it is a bug) prevents me to use the "windows-like" visibility feature of gcc 4.0. A short explanation: I have ported a project (one dll) from windows, that exports ca. 1200 symbols. After porting to Linux without using the "windows-like" visibility (exporting all symbols on the IF) the number of visible symbols was ca. 75000. I was really happy as I heard of the visibilty feature of gcc 4.0. I implemented that feature as described in http://gcc.gnu.org/wiki/Visibility. The result: The number of exported symols was ca:70000. And the test crashed. After several days I could identify the place of the crash, and I coud create this smaller example. If this "bug" is fixed, is still a question for me: Why is the big difference "1200-Windows" vs. "70000-Linux" in the exported symbols?
Oh, if you had put how you involved gcc in the comments instead of in build script, I would have seen what the problem is. Anyways this is a dup of bug 19664. The problem is the libstdc++'s headers don't have push/pop of the visibility. *** This bug has been marked as a duplicate of 19664 ***