2014-12-06 5 views
0

이 줄을 이해 도움말 및이 게시물에 건너 온 : 그것은 잘 작동하고 나는 VTABLE 항목을 통해 기능을 호출 할 수 있습니다 http://www.codeproject.com/Tips/90875/Displaying-vtable-when-debuggingC는 + + : 내가 포인터를 통해 직접 vtable에 액세스 할 수있는 방법을 찾고 있었다 코드

. 하지만 데오의이 행을 이해하는 데 문제가 :

void (**vt)() = *(void (***)())ptr; 

ptr는 객체에 대한 포인터입니다. 이 행을 어떻게 해독 할 수 있으며 vt은 vtable 주소를 얻는 방법은 무엇입니까?

감사합니다.

+0

관련 내용 : [이 사이트를보십시오] (http://cdecl.org)에서 유형을 설명합니다. – WhozCraig

답변

1

void (**vt)()
vt는 일부 함수에 대한 포인터의 포인터입니다. 이 함수는 void를 반환하고 매개 변수를 사용하지 않습니다.

은 그러한 함수에 대한 포인터에 대한 포인터 (즉, 위의 포인터 레벨보다 하나 더 높음)를 의미합니다.

먼저, 3 레벨 포인터로 함수에 ptr을 캐스팅하고 있습니다.
그런 다음 두 레벨 포인터 기능 (즉, 단일 *)이 가리키는 것을 얻습니다. 같은 유형의 변수 vt. 즉, vt에 할당 할 수 있다는 것을 의미합니다.이 라인이 실제로 무엇을하는지 알 수 있습니다.

왜?

void-no-param-function에 대한 단일 함수 포인터는 변수 x : void(*x)()에 저장 될 수 있습니다. 그리고 정확하게 관련이 없습니다. 배열에 함수를 전달하려면 포인터를 전달해야합니다. 예. 길이를 알고있는 경우 전체 배열에 액세스하기위한 포인터에 배열 주소를 저장하는 것으로 충분합니다.
즉, void(**vt)()은 함수 포인터 배열 (의 주소)을 저장할 수 있습니다.
vtable은 아무것도 아닌 함수 포인터의 배열입니다.

color 및 vtable과 같은 변수가있는 Car 클래스가 있고 예를 들어, 객체 당 200 바이트. 자동차에 대한 포인터는 200 바이트 배열에 대한 포인터와 같으며 코드에서 색상에 액세스하면 컴파일러는 해당 색상을 예를 들어 다음과 같이 찾습니다. 바이트 133에 대한 액세스를 생성한다.

vtable은이 개체 내에 있지만 구현 정의는 있지만 처음에는 종종 있습니다. 만약 당신이 자동차에 대한 포인터를 가지고 있다면, 그것은 200 바이트의 배열을 가리키는 포인터이고, 첫번째 포인터와 몇 개의 다른 포인터로 구분됩니다. ...

=> vtable, 즉. 함수 포인터의 배열은 자동차의 시작 주소에서 시작합니다.
=> 자동차 포인터를 vtable에 대한 포인터에 캐스트하면 즉, "함수 포인터 배열"에 대한 포인터, 즉. 포인터를 "함수 포인터"포인터로 옮겨 놓으면 vtable 배열을 가질 수 있습니다.

2

개체에서 _vtable의 실제 위치는 컴파일러에 따라 다릅니다. 이 코드는 _vtable 주소가 객체에 먼저 저장되어 있다고 가정합니다 (모든 현대 컴파일러가하는 것처럼 보임). 또한 한 위치에 저장되는 클래스 당 하나의 vtable 만 있습니다. 따라서 모든 인스턴스에는 함수에 대한 포인터 배열에 대한 주소가 있습니다.

기본적으로 void를 반환하고 매개 변수를 사용하지 않는 함수에 대한 포인터의 배열 인 vt라는 변수를 만듭니다. 그런 다음이 변수를 객체의 첫 번째 멤버 (vtable의 주소)에있는 내용으로 초기화합니다.

(void (***)())ptr 

는 무효 돌아가서 매개 변수를 취하지 함수 포인터들의 어레이에 대한 포인터로이 제 4 (32 비트 시스템) 또는 8 (64 비트 시스템)에 전송할 것을 의미한다.

*(void (***)())ptr 

은 vtable의 주소 인 4 또는 8 바이트의 내용을 반환합니다.