2009-05-12 3 views
4

Visual Studio를 사용하고 있으며 유효한 동적 캐스팅을 수행하고 있습니다. RTTI가 활성화됩니다.std :: __ non_rtti_object 예외가 생성되는 이유는 무엇입니까?

편집 :

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); 

내 디버거가 예외가 발생하는 경우 올바른 유형의 in_ptr 것을 말한다 더 현실적으로 코드를 업데이트했습니다. 구글은 특히 도움이되지 않는 것 같다. 어떤 아이디어? 건배.

+0

실제 코드를 게시하십시오. – dirkgently

+0

다음은 사용 시나리오입니다. UseNewSpec은 GUI 노브에 연결됩니다. 노브가 변경되면 UseNewSpec이 호출됩니다. 그것은 노브가 천천히 움직일 때 작동합니다, 그러나 정말로 빨리 움직일 때 이것을 제외하고 이것을 나타냅니다. – Carl

+0

감사합니다.나는 그것을 알아 냈다. 스레딩 문제였습니다. 일부 다른 코드는 dynamc 캐스트 바로 전에 포인터가 유효하지 않게되는 원인이되었습니다. – Carl

답변

5

의사 코드를 기반으로 테스트를 실행했는데 작동합니다. 따라서 빌드 구성에서 RTTI가 실제로 활성화 된 경우 게시 한 항목에 RTTI가 캡처되지 않는 또 다른 문제 여야합니다.

+3

누군가가이 게시물을 나중에 실행하면, 비슷한 문제가있어서 내 코드에서 뭔가 어리석은 짓을하고 있습니다.'dynamic_cast'에서 반환 된 (유효한, NULL이 아닌) 포인터에서 개체를 삭제하고 나중에 같은 원본 포인터에서'dynamic_cast'를 호출하기 시작했습니다. 아마도이 질문에 대한 문제는 아니지만 다른 사람이이 질문을 간단하게 확인할 수있는 경우에 대비하여이 점을주의해야합니다. –

+2

그것은 나에게 매우 비슷한 문제였습니다. 차이점은 내가 사용하고 있던 포인터를 삭제하는 다른 곳의 코드가 포인터를 NULL로 설정하지 않았다는 것입니다. 따라서 유효 해 보였지만 동적 캐스팅은 여전히 ​​실패했습니다. – Carl

+2

은 당신보다 더 똑같은 문제가있었습니다. 매달려있는 포인터에'dynamic_cast <>'를 호출했습니다. 감사 – azf

5

dynamic_cast와 관련된 예외, 오류 또는 오류는 사용자가 불법 전송을 수행했다는 것을 의미 할 수 있습니다. dynamic_cast<derived*>(ptrToBase)은 클래스 derived 및 클래스 base이 둘 다 다음 제한 조건을 충족시키는 경우에만 유효합니다. 해당 클래스 또는 기본 클래스 중 하나에 가상 멤버 함수가 있습니다.

이 가상 멤버 함수는 소멸자를 포함하여 무엇이든 될 수 있습니다.

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

struct derived : public base 
{ 
    ... 
} 

지금 base 가상 멤버 함수를 가지고 있으며, 그래서 파생 않습니다 당신이 다른 멤버 함수가없는 경우 시도 할 수 있습니다. 문제를 해결하는지 확인해보십시오.

편집-ADD :

@carleeto -, 그것은 미상 == 기본 "이미 가상 소멸자를했다"?

파생 된 파생 가상 소멸자가 있지만 기본 가상 아닌 dtor 경우이 오류가 계속 발생할 수 있습니다.

또한 소멸자가 실행되면 개체가 소멸되지 않았는지 확인해야합니다. 즉, dynamic_cast는 더 이상 안전하게 호출 할 수 없습니다. ctors와 dtors에 추적을 추가하십시오.

+0

이미 가상 소멸자가 있습니다. 내 잘못 - 내가 지적 했어야 했어. – Carl

+0

@carleeto - 편집 추가, 새로운 답변을 – Aaron

0

base에는 virtual 메서드가 있습니까? dynamic_cast을 사용하려면 작동해야합니다.

+0

예. 죄송합니다. 코드에 추가해야합니다. – Carl

+0

방금 ​​코드를 업데이트했습니다. – Carl

8

http://msdn.microsoft.com/en-us/library/fyf39xec(VS.80).aspx에는 __non_rtti_object_exception에 대한 정보가 있습니다. MSDN에서

: 포인터가 유효한 개체를 가리 키지 않는 경우

하는 __non_rtti_objectexception는 는 (액세스 위반 등) 장애를 유발하는 RTTI를 분석하는 시도를 나타내는 발생합니다 그 이유는 객체가 인데, 잘못된 포인터이거나 잘못된 포인터이거나 코드가/GR로 컴파일되지 않았기 때문입니다.

+0

/GR은 RTTI를 사용함을 의미합니다. 이미 기본적으로 사용하도록 설정되어 있습니다./GR- 끄기. 명시 적으로/GR을 명령 줄에 추가하는 것조차 도움이되지 않습니다. – Carl

1

모든 소스 파일에서 RTTI를 사용하도록 설정했는지 확인하십시오.

그렇지 않으면 포인터가 유효하지 않습니다.

관련 문제