가상 주소를 멤버 함수 포인터의 정수로 가져올 수 있습니까?멤버 함수 포인터가 정수를 가리키는 포인터입니까?
나는 시도했다.
void (AClass::*Test)(); Test = &AClass::TestFunc; int num = *(int*)&Test;
하지만 모든 기능은 jmp의 가상 주소를 가져옵니다. 실제 기능 가상 주소가 필요합니다.
가상 주소를 멤버 함수 포인터의 정수로 가져올 수 있습니까?멤버 함수 포인터가 정수를 가리키는 포인터입니까?
나는 시도했다.
void (AClass::*Test)(); Test = &AClass::TestFunc; int num = *(int*)&Test;
하지만 모든 기능은 jmp의 가상 주소를 가져옵니다. 실제 기능 가상 주소가 필요합니다.
이식성있는 방법이 있는지 여부를 명확히 말할 수는 없지만 일반적으로 정적 메서드를 만들어 클래스 메서드에 대한 외부 액세스를 제공하는 것이 좋습니다. 그렇지 않으면 당신이 성공하더라도 당신은 그 클래스 구현에 대한 어플리케이션의 매우 단단한 결합을 만들 것입니다.
아니요, 멤버 함수 포인터는 a variety of sizes (플랫폼에 따라 4-16 바이트 이상, 기사의 표 참조) 일 수 있으며 정수 공간 내에 안정적으로 들어갈 수 없습니다. 이것은 가상 함수와 상속으로 인해 컴파일러가 여러 함수를 호출하여 올바른 함수를 호출 할 수 있기 때문에 단순한 주소가없는 경우가 있기 때문입니다.
이것이 의심스러운 경우 증분 링크를 해제하십시오. 그 동안 올바른 답을 얻고 있습니다.
다른 내 생각에 TestFunc
은 virtual
일 수 있습니다. 주소가 찍힌 가상 함수의 경우 VC++은 vtable 조회를 수행하는 약간의 썽크를 가짜로 만들고 해당 썽크에 대한 포인터를 주소로 제공합니다. (실제 파생 된 파생 된 형식의 경우 파생 된 올바른 함수를 찾을 수 있습니다.이 작업을 수행하는 다른 방법이 있지만이 포인터를 단일 포인터 수 및 호출 코드를 단순화 할 수 있습니다. 점프 할 때 점프.) 프로그램의 어셈블리 언어 출력을 켜고 결과를 살펴 봅니다. 무슨 일이 일어나고 있는지 분명해야합니다.
여기서도 올바른 대답을 얻을 수 있으며 '실제'기능의 주소를 찾을 방법이 없습니다. 실제로, 가상 함수는 하나의 실제 함수를 명명하지 않고, 파생 된 함수가 문제의 객체에 적합한 지 여부를 지정합니다. (이 동작이 마음에 들지 않으면 함수를 가상이 아닌 것으로 만드십시오.) 실제 함수의 실제 주소가 실제로 필요한 경우 두 가지 옵션이 있습니다.
성가신 하나는 함수의 vtable 인덱스를 찾기 위해 썽크를 검사하는 코드를 작성하는 것입니다. 그런 다음 해당 객체의 vtable을보고 해당 함수를 가져옵니다.
(하지만 비 가상 함수의 주소를 사용하면 호출 할 실제 함수의 주소를 알 수 있으며 썽크가 아니라는 점에 유의하십시오. 따라서이 가능성도 고려해야합니다. 가상 함수에 대한 포인터와 비가 상 함수에 대한 포인터는 동일합니다.)
더 쉬운 방법은 각 가상 함수에 대한 코드가 포함 된 비 가상 함수를 만든 다음 각 가상 함수가 비표준 함수를 호출하도록하는 것입니다. 가상 기능. 그것은 이전과 같은 행동을합니다. 그리고 코드가 어디에 있는지 알아 보려면 비 가상 함수의 주소를 가져옵니다.
(두 경우 모두이 작업을 잘 수행하기가 어려우며 성가신 일이 될 수 있으며 VC++에만 해당 될 수 있습니다. 그러나 노력을 기울이면 기꺼이 수행 할 수 있습니다. .)
나는 이것이 오래되었다는 것을 알고있다. 그러나 의미있는 주제에 대한 대답이 없기 때문에 여기에 나는 간다.
먼저 몇 가지 사항을 고려해야합니다. C++의 멤버 함수 호출 규칙을 __thiscall이라고합니다. 이 규약은 __stdcall과 거의 동일하지만 유효 호출이 이루어지기 전에 ECX
이 호출되는 객체의 this
포인터로 설정된다는 점이 중요한 차이점입니다.
이를 설명하고 동시에 귀하의 질문에 대답,의 클래스 AClass
는 다음과 같이 선언 된 멤버 함수가 있다고 가정 해 봅시다하려면 int AClass::myFunction(int a, int b)
을 우리가 aClassObject
라는 AClass
의 인스턴스를 가지고있다.
// declare a delegate, __stdcall convention, as stated above
typedef int (__stdcall *myFunctionDelegate)(int a, int b);
// here's the 'hackish' solution to your question
char myFunctionPtrString[10];
sprintf(myFunctionPtrString, "%d", &AClass::myFunction);
int myFunctionPtr = atoi(myFunctionPtrString);
// now let's call the method using our pointer and the aClassObject instance
myFunctionDelegate myFunction = (myFunctionDelegate)myFunctionPtr;
// before we make the call, we must put a pointer to aClassObject
// in ECX, to finally meet the __thiscall calling convention
int aClassObjectPtr = (int)&aClassObject;
__asm{
mov ecx, aClassObjectPtr
}
// make the call!
myFunction(2, 3);
그리고 물론
는, 인스턴스 유형AClass
의 인스턴스가 될 수 있습니다 다음은 원시 포인터를 얻을 후 처음 요구와
aClassObject
에
AClass::myFunction
전화를 '시뮬레이션'무엇을 할 수있는 다소 hackish 방법 .
건배,
Zozel
그것은 가상 아닙니다. 그것은 수입이지만. – user230821
증분 연결을 해제 한 다음 시도해보십시오. 이 경우 각 외부 함수는 jmp를 실제 주소로 처리하는 코드를 통해 호출됩니다. (변경되지 않은 모듈은 호출 당 하나가 아닌 externed 함수 당 하나의 픽스 업만 필요하기 때문에 이전 링킹에서 데이터를 더 잘 재사용 할 수 있습니다.) –