This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

libstdc++/4993: dynamic_cast incorrectly returns 0



>Number:         4993
>Category:       libstdc++
>Synopsis:       dynamic_cast incorrectly returns 0
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Dec 03 12:26:01 PST 2001
>Closed-Date:
>Last-Modified:
>Originator:     Philip Hubbard / Florian Kainz, Industrial Light + Magic
>Release:        unknown-1.0
>Organization:
>Environment:
gcc 3.0.1 / 3.0.2 on RedHat Linux 7.1 / Pentium

                 % g++ -v
                 Reading specs from /usr/local/lib/gcc-lib/i686-pc-linux-gnu/3.0.1/specs
                 Configured with: ../gcc-3.0.1/configure --enable-threads --prefix=/usr/local
                 --enable-languages=c,c++
                 Thread model: posix
                 gcc version 3.0.1
>Description:
dynamic_cast incorrectly returns 0 in programs that load 
dynamic shared objects (DSOs) via dlopen(). 

Header file <typeinfo> assumes that typeinfo names are merged
across all DSOs in a program if weak symbols are supported.
At least on Linux, this assumption is wrong for DSOs loaded
via dlopen().

Note: This is more or less the same bug report as #4292; a workaround 
was suggested for #4292, and the case was closed.  The workaround -- 
using dlopen(..., RTLD_NOW | RTLD_GLOBAL) -- does not work, so I am 
resubmitting the bug with an updated example.

>How-To-Repeat:
Reproducing the bug requires multiple source files:

                 a.C a.h main.C Makefile

                 The files are listed below.

                 The example program should print:

                 castInMain()
                 1
                 castInDso()
                 1
                 castInMain()
                 1
                 castInDso()
                 1

                 The program prints this instead:

                 castInMain()
                 1
                 castInDso()
                 0
                 castInMain()
                 0
                 castInDso()
                 1

                 The source files:

                 ::::::::::::::
                 a.C
                 ::::::::::::::
                 #include <a.h>
                 #include <iostream>

                 extern "C"
                 {
                 D *
                 DInDso ()
                 {
                 static D d;
                 return &d;
                 }

                 bool
                 castInDso (B *b)
                 {
                 std::cout << "castInDso()\n";
                 return 0 != dynamic_cast <D *> (b);
                 }
                 }

                 ::::::::::::::
                 a.h
                 ::::::::::::::
                 struct B
                 {
                 virtual ~B() {}
                 };

                 struct D: public B
                 {
                 virtual ~D() {}
                 };

                 ::::::::::::::
                 main.C
                 ::::::::::::::
                 #include <a.h>
                 #include <dlfcn.h>
                 #include <iostream>

                 using std::cout;
                 using std::endl;

                 extern "C"
                 {
                 typedef bool func1 (B *);
                 typedef D * func2 ();
                 }

                 bool
                 castInMain (B *b)
                 {
                 std::cout << "castInMain()\n";
                 return 0 != dynamic_cast <D *> (b);
                 }

                 int
                 main ()
                 {
                 void *liba = dlopen ("./liba.so", RTLD_NOW | RTLD_GLOBAL);

                 if (!liba)
                 {
                 cout << dlerror () << endl;
                 return 1;
                 }

                 func1 *castInDso = (func1 *) dlsym (liba, "castInDso");

                 if (!castInDso)
                 {
                 cout << dlerror () << endl;
                 return 1;
                 }

                 func2 *DInDso = (func2 *) dlsym (liba, "DInDso");

                 if (!DInDso)
                 {
                 cout << dlerror () << endl;
                 return 1;
                 }

                 {
                 D d;
                 cout << castInMain (&d) << endl;
                 cout << castInDso (&d) << endl;
                 }

                 {
                 D *d = DInDso();
                 cout << castInMain (d) << endl;
                 cout << castInDso (d) << endl;
                 }
                 }

                 ::::::::::::::
                 Makefile
                 ::::::::::::::
                 t = liba.so test 

                 all: $t

                 clean:
                 rm -f $t core

                 liba.so: a.C a.h
                 g++ -I. -shared -o $@ a.C

                 test: main.C a.h
                 g++ -I. -L. main.C -o $@ -ldl
>Fix:
*** gcc-3.0.1/libstdc++-v3/libsupc++/typeinfo Wed Jul 11 12:37:58 2001
                 --- /net/rnd/gs/home/kainz/pub/gcc-3.0.1/libstdc++-v3/libsupc++/typeinfo 
                 Mon Sep 10 15:23:30 2001
                 ***************
                 *** 43,54 ****
                 class __class_type_info;
                 } // namespace __cxxabiv1

                 ! #if !__GXX_WEAK__
                 ! // If weak symbols are not supported, typeinfo names are not merged.
                 ! #define __GXX_MERGED_TYPEINFO_NAMES 0
                 #else
                 ! // On platforms that support weak symbols, typeinfo names are merged.
                 ! #define __GXX_MERGED_TYPEINFO_NAMES 1
                 #endif

                 namespace std 
                 --- 43,65 ----
                 class __class_type_info;
                 } // namespace __cxxabiv1

                 ! #if 0
                 ! 
                 ! #if !__GXX_WEAK__
                 ! // If weak symbols are not supported, typeinfo names are not merged.
                 ! #define __GXX_MERGED_TYPEINFO_NAMES 0
                 ! #else
                 ! // On platforms that support weak symbols, typeinfo names are merged.
                 ! #define __GXX_MERGED_TYPEINFO_NAMES 1
                 ! #endif
                 ! 
                 #else
                 ! 
                 ! // Even if weak symbols are supported, typeinfo names are not
                 ! // always merged. On Linux, dynamic shared objects opened with
                 ! // dlopen() have their own, non-shared copies of typeinfo names.
                 ! #define __GXX_MERGED_TYPEINFO_NAMES 0
                 ! 
                 #endif

                 namespace std 
>Release-Note:
>Audit-Trail:
>Unformatted:


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]