When and why is an std::__non_rtti_object exception generated?

匿名 (未验证) 提交于 2019-12-03 01:22:02

问题:

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.

回答1:

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.



回答2:

http://msdn.microsoft.com/en-us/library/fyf39xec(VS.80).aspx 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).



回答3:

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.



回答4:

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

Otherwise the pointer is invalid.



回答5:

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



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!