libstdc++/4292: dynamic_cast incorrectly returns 0

kainz@ilm.com kainz@ilm.com
Mon Sep 10 16:06:00 GMT 2001


>Number:         4292
>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 Sep 10 16:06:01 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator:     Philip Hubbard / Florian Kainz, Industrial Light + Magic
>Release:        unknown-1.0
>Organization:
>Environment:
gcc 3.0.1 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().
>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_LAZY);

    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:



More information about the Gcc-bugs mailing list