9

I'm using Visual Studio and performing a valid dynamic cast. RTTI is enabled.

Edit : Updated the code to be more realistic

struct base
{
    virtual base* Clone()
    {
        base* ptr = new base;
        CopyValuesTo( ptr );
        return ptr;
    }
    virtual void CopyValuesTo( base* ptr )
    {
       ...
    }
    virtual ~base()
    {
    }
}

struct derived : public base
{
    virtual base* Clone()
    {
        derived* ptr = new derived;
        CopyValuesTo( ptr );
        return ptr;
    }
    virtual void CopyValuesTo( base* ptr )
    {
       ...
    }
    virtual ~derived()
    {
    }
}  

void Class1::UseNewSpec( base* in_ptr ) //part of a totally unrelated class
{
    derived* ptr = dynamic_cast<derived *>(in_ptr);
    if( !ptr )
       return;
    delete m_ptr;
    m_ptr = ptr->Clone(); //m_ptr is a member of Class1 of type base*
}

//usage : 
Class1 obj;
derived new_spec; 
obj.UseNewSpec( &new_spec );

My debugger says that in_ptr is of the correct type when the exception is thrown. Google seems particularly unhelpful. Any ideas? Cheers.

Carl
  • 43,122
  • 10
  • 80
  • 104
  • Here's a usage scenario: UseNewSpec is linked to a GUI knob. When the knob is changed, UseNewSpec is called. It works when the knob is moved slowly, but thows this exceptoin when its moved really fast. – Carl May 12 '09 at 21:37
  • Thanks guys. I've figured it out. It was a threading issue - some shoddy code elsewhere was causing the pointer to become invalid just before the dynamc cast. – Carl May 12 '09 at 22:36

5 Answers5

9

https://learn.microsoft.com/en-us/cpp/cpp/typeid-operator?view=vs-2019 has info on __non_rtti_object_exception.

From MSDN:

If the pointer does not point to a valid object, a __non_rtti_objectexception is thrown, indicating an attempt to analyze the RTTI that triggered a fault (like access violation), because the object is somehow invalid (bad pointer or the code wasn't compiled with /GR).

Code Doggo
  • 2,146
  • 6
  • 33
  • 58
Michael
  • 54,279
  • 5
  • 125
  • 144
  • /GR means enable RTTI. It is already enabled by default. /GR- turns it off. Even explicitly adding /GR to the command line doesn't help. – Carl May 12 '09 at 21:33
6

RTTI exceptions, failures, or errors around a dynamic_cast can mean that you performed an illegal cast. dynamic_cast<derived*>(ptrToBase) is valid if and only if class derived and class base both meet the following constraint: that class, or one of its base classes, has a virtual member function.

This virtual member function can be anything, including the destructor. If you don't have any other member functions, you can try:

struct base
{
    virtual ~base(){}
    ...
}

struct derived : public base
{
    ...
}

Now base has a virtual member function, and so does derived. Try that out and see if it resolves your issue.

EDIT-ADD:

@carleeto -- In "it already had a virtual destructor", doe it==base?

If derived has virtual destructor but base is non-virtual dtor, then you may still get this error.

Also, you should verify that the object hasn't been destructed -- once the destructor runs, dynamic_cast is no longer safe to call. Try adding a trace to the ctors and dtors.

Aaron
  • 3,454
  • 23
  • 26
6

I ran a test based on your pseudo-code and it works. So if RTTI is truly enabled in your build configuration, then it must be another problem that isn't captured in what you posted.

Skrymsli
  • 5,173
  • 7
  • 34
  • 36
  • 5
    In case someone runs into this post in the future, I had a similar problem and it turned out I was doing something foolish in my code: I deleted an object on the (valid, non-NULL) pointer returned from `dynamic_cast` and then proceeded to call `dynamic_cast` on the same original pointer later on. That probably isn't the problem for this question, but I'm just noting this in case someone else stumbles into this question as something simple to check for. – Dan Nissenbaum Nov 18 '12 at 03:04
  • 2
    It was a very similar problem for me. The difference was that the shoddy code elsewhere that was deleting the pointer I was using was not even setting the pointer to NULL. Therefore, it looked valid, but the a dynamic cast still failed. – Carl Nov 18 '12 at 20:01
  • 2
    had same problem than you guys, calling `dynamic_cast<>` on dangling pointer. thanks – azf Oct 15 '13 at 18:53
1

Make doubly sure you have RTTI enabled in all source files.

Otherwise the pointer is invalid.

null
  • 878
  • 6
  • 11
0

Does base contain any virtual methods? It must in order for dynamic_cast to work.

j_random_hacker
  • 50,331
  • 10
  • 105
  • 169