2012-08-01 2 views
1

가상 함수 테이블이 0을 가리키는 개체에서 가상 함수를 호출하려고하기 때문에 발생하는 응용 프로그램의 액세스 위반을 분석하고 있습니다. 객체의 수명에서 가상 함수 테이블 포인터가 설정되지 않았거나 명시 적으로 0으로 설정된 점은 무엇입니까?가상 함수 테이블이 0으로 설정되는시기는 언제입니까

(우리는 컴파일러로 비주얼 C++ (10)를 사용합니다.)

+0

코드에서 문제를 재현 할 수 있다면 문제를 해결하는 것이 더 쉬울 수 있습니다. 건설중인 물건을 오용하여 UB의 인스턴스가 생겼을 수도 있습니다. –

+0

이것은 잘못된 접근 방식처럼 느껴집니다. 먼저 메모리 디버거를 사용하여 프로그램을 실행하고 무언가를 이중으로 삭제하지 않을 것인지 아니면 그 라인을 따라 무언가를 삭제하는지 확인하십시오. –

+0

불행히도 우리 개발 시스템에서 문제가 발생하지 않기 때문에 분석 할 덤프 파일 만 있습니다. – fschoenm

답변

2

객체가 유효한 상태에있는 동안 vtable에 포인터가 0이되지 않습니다. 생성 및 소멸 중에 객체에 동적 기본 유형의 추상 기본 클래스가있는 경우 vtable은 순수 가상 함수를 포함하는 추상 기본 클래스 vtable을 가리키지 만 vtable 포인터 자체는 여전히 0이 아닙니다.

vtable 포인터가 0 일 수있는 유일한 시간은 생성 전이나 삭제 후입니다.

+0

내 클래스의 마지막 소멸자가 명시 적으로 vtable 포인터를 0으로 설정합니까? 그렇다면 내가 삭제해야하지만 아직도 메모리에 덮어 쓰기 전까지는 더 이상 손상되지 않은 객체를 다루고 있다고 가정합니다. – fschoenm

+0

(개체가 완전히 파괴되면 상태에 대한 요구 사항이 없어도됩니다.) 그렇게하지 않으면 오류를 catch하는 데 도움이됩니다. 대안은 메모리 손상입니다. – ecatmur

+0

이것은 그랬습니다 : 개체가 이미 파괴되었지만 다른 스레드에서 액세스 위반이 레이싱 조건에 영향을받습니다. – fschoenm

1

vtable에 포인터가 진정 제로의 경우, 당신은 같은 VC++ 확장을 사용하고 있습니다 : 어떤 가상 함수가 될 수 없기 때문에,

class __declspec(novtable) Base { 
public: 
    Base(); 
    virtual void proc(); 
}; 
다음 __declspec(novtable)

클래스가 vtable에 필요하지 않습니다 컴파일러를 알려줍니다 파생 클래스가 자체 vtable을 설치할 때까지 호출됩니다. 그런 다음 Base :: proc()을 호출하면 오류가 발생할 수 있습니다.

더 가능성이 VTABLE 자체가 비 제로이지만, 함수의 슬롯은 가상 순수되는 인한 기능, 제로 : 다음

class Base { 
public: 
    virtual void proc() = 0; 
}; 

누군가와 함께 어쨌든라는 코드 같은 :

void Derived::proc() { 
    Base::proc(); 
    // Derived-specific stuff here. 
}; 

이것은 파생물 작성자가 기본 버전이 존재하지 않아도 기본 버전을 호출하는 데 필요한 재정의를 가정했기 때문에 발생할 수 있습니다.

어느 쪽이든,이 방법을 찾는 한 가지 방법은 모든 기본 클래스의 속임수를 중지하고, 함수를 정상적으로 정의하며, 무엇을 호출하는지 확인하는 것입니다. 예 :

class Base { 
public: 
    virtual void proc() { 
     assert(typeof(*this) != typeof(Base)); // Break-point here. 
    } 
}; 
+0

어느 쪽도 아니야. 디버거는 명시 적으로 vtable 포인터가 0으로 표시되므로 개별 항목을 표시 할 수도 없습니다. – fschoenm