Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

#152 GCC 3.1 dynamic_cast fails with DLLs

closed-fixed
Danny Smith
gcc (462)
2014-08-28
2002-06-12
Colin Peters
No

When attempting to use dynamic_cast in an
executable to cast a base class pointer to an instance
produced in a DLL to a derived class dynamic_cast
fails, returning zero. e.g.

class cFoo { ... };
class cBar : public cFoo { ... };

cFoo* pfoo = CreateBarInDLLAndCastToFoo();
cBar* pbar = dynamic_cast<cBar*>(pfoo);

pbar ends up zero.

The same code works as expected when compiled into
a single executable or when I revert to gcc 2.95.3 and
an older version of binutils.

Attached is a simple test case demonstrating the
problem. main.cpp is the executable, while foobar.cpp
is built into a DLL. Doing a "make test" builds a static
version static.exe and dynamic version dll.exe, then
runs both. Sample output is included for make test
with gcc 2.95.3 (old.out) and gcc 3.1 (new.out).

If the test works properly, the printed output for
the "Bar pointer" will be non-zero in both static and
DLL cases.

Note: The Makefile as it is builds with the -v flag. I also
only used it under bash and with working versions of
rm and echo available.

Discussion

  • Colin Peters
    Colin Peters
    2002-06-12

    Test case files and output

     
    Attachments
  • Danny Smith
    Danny Smith
    2002-06-13

    Logged In: YES
    user_id=11494

    Thanks for the report. This will be a challenge.

    typinfo implementation has changed quite a bit.
    Compare the assemby code for main.cpp in 2.95.3 and
    3.1.

    2.95: typeinfo is accessed through function

    3.1: typinfo variable accessed directly

    DATA gets prefixed with _imp_ in dll lib so maybe the
    problem is in .linkonce not working.
    In 2.95 with access through .linkonce function there is
    no problem because function name isn't decorated
    I've got some digging to do.

    Danny

     
  • Danny Smith
    Danny Smith
    2002-06-16

    Logged In: YES
    user_id=11494

    Actually gcc FAQ has a section entitled:
    "dynamic_cast, throw, typeid don't work with shared
    libraries" but it seems to be talking about platforms
    that have weak linkage and use addresses to determine
    type equality. w32 targets still uses string
    comparisons. Any ideas?

    Danny

     
  • Luke Dunstan
    Luke Dunstan
    2002-06-17

    Logged In: YES
    user_id=30442

    In tinfo.cc:

    #if !__GXX_MERGED_TYPEINFO_NAMES

    // We can't rely on common symbols being shared between
    shared objects.
    bool std::type_info::
    operator== (const std::type_info& arg) const
    {
    return (&arg == this) || (__builtin_strcmp (name (), arg.name
    ()) == 0);
    }

    #endif

    In <typeinfo>:

    #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

    However, in cppinit.c:

    if (SUPPORTS_ONE_ONLY)
    _cpp_define_builtin (pfile, "__GXX_WEAK__ 1");
    else
    _cpp_define_builtin (pfile, "__GXX_WEAK__ 0");

    And in defaults.h:

    /* This determines whether or not we support link-once
    semantics. */
    #ifndef SUPPORTS_ONE_ONLY
    #ifdef MAKE_DECL_ONE_ONLY
    #define SUPPORTS_ONE_ONLY 1
    #else
    #define SUPPORTS_ONE_ONLY 0
    #endif
    #endif

    So possibly GXX_WEAK is a misnomer because it is defined
    when linkonce is supported, not weak symbols.

    Test this for Mingw with:

    $ echo __GXX_WEAK__ | cpp -x c++
    # 1 "<stdin>"
    # 1 "<built-in>"
    # 1 "<command line>"
    # 1 "<stdin>"
    1

     
  • Danny Smith
    Danny Smith
    2002-08-01

    • status: open --> pending-fixed
     
  • Danny Smith
    Danny Smith
    2002-08-01

    Logged In: YES
    user_id=11494

    Fixed in cygwin-mingw-gcc-3_2-branch of FSF CVS
    Danny

     
  • Danny Smith
    Danny Smith
    2002-08-26

    • status: pending-fixed --> closed-fixed
     
  • Danny Smith
    Danny Smith
    2002-08-26

    Logged In: YES
    user_id=11494

    The problem you report has caused modification in some fashion in the official CVS for the given package. The w32api and
    mingw-runtime official CVS reside in the winsup CVS directory tree for Cygwin. Those package CVS trees are periodically
    merged into the MinGW CVS tree. If you still find problems then please open a new report.