문제
나는 Vtable Thunks와 관련하여 그물에 관한 기사를 읽고 있었고, 나는 덩어리를 사용하여 절차 호출을 고치는 데 사용될 수 있다는 것을 읽었습니다.
달성 할 수 있습니까?
누구든지 그것이 어떻게 작동하는지 알고 있습니까? 그것에 대한 제안이 있습니까?
해결책
V- 테이블 펑크 스타일로 생생한 펑크를 구현하는 것은 마지막 수단입니다. 당신이 달성해야 할 것은 래퍼 기능으로 달성 될 수 있으며 훨씬 덜 고통 스럽습니다.
일반적으로 Thunk는 다음을 수행합니다.
- 입력 매개 변수 수정 (예 : 다른 형식으로 변환)
- 실제 구현을 호출하십시오
- 1 단계 정리 / 출력 매개 변수를 수정하십시오
그것이 어떻게 작동하는지에 대한 예를 보려면 우리의 좋은 친구 Raymond Chen과 그의 조정자 덩어리에 대한 그의 토론을 봅시다.
http://blogs.msdn.com/oldnewthing/archive/2004/02/06/68695.aspx
그가 사용한 멍청한 것은 다음과 같습니다.
[thunk]:CSample::QueryInterface`adjustor{4}':
sub DWORD PTR [esp+4], 4 ; this -= sizeof(lpVtbl)
jmp CSample::QueryInterface
그가 설명 하듯이 여러 인터페이스를 통해 동일한 방법을 구현하는 클래스가 있으므로 여러 V 테이블이 있습니다. (COM을 모르는 경우 V- 테이블과 직접 작동한다는 점에서 알아야 할 것은 특정 인터페이스에 대한 포인터에는 해당 인터페이스의 모든 방법에 대한 기능 포인터가 포함되어야합니다. 순서대로.)
특정 슬롯에서 다른 메소드가있는 두 개의 인터페이스를 구현하면 여러 V 테이블이 필요합니다. 그러나 겹치는 방법을 한 번만 작성하므로 그 방법은 두 "이"포인터와 함께 작동 할 수 있어야합니다. 이를 위해 컴파일러는 Fixup이 필요한 방법을 생성하고 원래 구현을 호출하는 메소드를 생성합니다.
따라서이 펑크는 다음과 같은 단계를 수행합니다.
- 첫 번째 줄에서 입력 매개 변수, 즉 숨겨진 "이"포인터를 고정하십시오.
- 두 번째 줄에서 실제 구현을 호출하십시오.
- 정리 : 필요 없음 (아래 참조)
이것은 어디에 있습니다 jmp
명령어가 들어온다. 일반적으로, 당신이 사용 함수를 호출하려면 call
, 그것은 당신에게 돌아올 것이고, 당신은 ret
발신자로 돌아갑니다. 정리가 없기 때문에 컴파일러는 실행을 실제 구현으로 바로 이동하고 실제 구현의 리턴 명령문이 당신의 방문객. 이것은 단지 최적화 일 뿐이며 펑크의 기본 부분이 아닙니다. 예를 들어, 16 / 32 비트 펑크는 필요에 따라 입력 / 출력 매개 변수를 16 ~ 32 비트 사이로 변환하므로 정리 단계를 건너 뛸 수 없습니다. 해야합니다 call
, 아니다 jmp
.
이야기의 도덕은 다음과 같은 일을해야한다면 jmp
최적화, C ++ 또는 다른 높은 수준의 선택 언어로 직접 쓸 수 없다는 최적화는 계속해서 어셈블리 언어를 작성하십시오. 그렇지 않으면 래퍼를 작성하고 완료하십시오.
솔직히 말해서, 성능 최적화를 요구하는 것처럼 들리며, 대부분의 시간 (1) 컴파일러는 우리가 생각하는 것보다 최적화하는 데 더 잘 적용되며 (2) 생각하는 것만 큼 큰 개선을 제공하지 않을 것입니다.
다른 팁
글쎄, 당신은 펑크가 해결책이라는 것을 읽었으며 이제 해결해야 할 문제를 찾고 있습니까?
일반적으로 Thunks는 일반적으로 짧은 "전달"기능입니다.
vtable 청크는 매우 잘 설명됩니다 위키 백과 현재. 공통 패턴을 사용합니다. 런타임에 계산 / 추가 작업을 피하기 위해 작은 기능을 생성합니다.
내가 본 / 사용한 다른 장소 :
창 핸들을 창 객체와 연관 : 각 창을 서브 클래스로 만들려면 객체 참조와 함께 창 절차를 호출하는 작은 덩어리가 생성되면 덩어리는 창 절차로 사용됩니다.
지연 DLLS : 펑크는 기능이 처음 호출 될 때 DLL을로드했는지 확인합니다.
COM 인터페이스 호출 트래핑 : Thunks는 진단에 대한 주입 지점을 제공하고 실제 방법으로 이동합니다.