This is the mail archive of the gcc-help@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]

strange dynamic_cast problem


Ok...this seems to be treading into some really esoteric areas of c++.
I will do my best to explain this issue, but I don't fully understand
what is happening myself. I am hoping that the problem comes down to
standard c++ stuff and is not specific to Mac OS X compiler&linker.

I have put together a simple test project which can be found at:

http://ericgorr.net/LibraryLoading.zip

which demonstrates the problem.

In Shared.h, there are the definitions of two purely virtual classes -
A & B. B is a subclass of A.

In LibraryA, there is a implementation of class B called BImp. There
is a function called GetA which returns a pointer to an instance of
BImp and returns an A*.

In LibraryB, there is a function called test. This function takes a
void *, which will end up being a function pointer to the GetA
function from LibraryA.

The problem comes in the test function with the line:

B* myB = dynamic_cast<B*> (myA);

The dynamic_cast fails and myB is assigned NULL. This _should not_
fail because myA is an instance of class B.

However, I can make this dynamic_cast succeed, if in main.cp, which is
a part of the Application target, I set:

#define CASE_A 1

which allows

         A *myA = functionPtr();
         B *myB = dynamic_cast<B*> (myA);

to be executed before the test function from LibraryB is called.

Any idea why this allows it to work?
Any idea why it is failing in the first place?

In main.cp, there are two #define's.

#define CASE_A 0
#define CASE_B 0

If both are set to zero, it will crash. This is simplest crashing
case.
If CASE_A is 1, it will work. Any idea why?
If CASE_B is 1, it will crash and this is the case closest to the real
case I am working with.

Since I started composing this message, I've been looking into the
issue a bit more and thought that if it were possible to make the
destructors pure virtual functions as well, then that would solve the
problem.

Googling for "pure virtual destructors c++", I came across:

http://www.linuxtopia.org/online_books/programming_books/thinking_in_...

While it seems strange, apparently this is allowed in C++.

So, if I changed Shared.h to look like:

*****
*****
#define VISIBLE __attribute__ ((visibility("default")))

class VISIBLE A
{
public:
    virtual ~A( void )          = 0;
    virtual void Func( void )   = 0;
};

A::~A() {}

class VISIBLE B : public A
{
public:
    virtual ~B( void )          = 0;
    virtual void Func1( void )  = 0;
};

B::~B() {}

extern "C" VISIBLE A *GetA( void );
*****
*****

everything worked in all three cases.

Any comments on this solution? Any reason why this wouldn't be
perfectly valid?

Any thoughts or comments would be appreciated.


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