исходный код: Код (Text): class UNetworkHandler; typedef User* (UNetworkHandler::*T_GetUser)(int a1); ... __declspec(dllexport) UNetworkHandler *g_NetworkHandler; __declspec(dllexport) T_GetUser GetUser; ... __debugbreak(); User *U = (g_NetworkHandler->*GetUser)(g_UserID); __debugbreak(); результат: Код (Text): .text:1000127B int 3 ; Trap to Debugger .text:1000127C mov ecx, dword_10013B84 .text:10001282 test ecx, ecx .text:10001284 jnz short loc_10001295 .text:10001286 mov eax, UNetworkHandler * g_NetworkHandler .text:1000128B mov ecx, dword_10013B7C .text:10001291 add ecx, eax .text:10001293 jmp short loc_100012B0 .text:10001295 ; --------------------------------------------------------------------------- .text:10001295 .text:10001295 loc_10001295: ; CODE XREF: sub_10001270+14j .text:10001295 mov eax, dword_10013B80 .text:1000129A mov edx, UNetworkHandler * g_NetworkHandler .text:100012A0 mov esi, [eax+edx] .text:100012A3 mov ecx, [esi+ecx] .text:100012A6 add ecx, eax .text:100012A8 add ecx, dword_10013B7C .text:100012AE add ecx, edx .text:100012B0 .text:100012B0 loc_100012B0: ; CODE XREF: sub_10001270+23j .text:100012B0 mov edx, ulong g_UserID .text:100012B6 push edx .text:100012B7 call User * (UNetworkHandler::*GetUser)(int) .text:100012BD int 3 ; Trap to Debugger чтоета??? ЗЫ: msvc2008, настройки - релиз
мне непонятно почему вместо int3 push ulong g_UserID mov ecx, UNetworkHandler * g_NetworkHandler call User * (UNetworkHandler::*GetUser)(int) int3 получилась эта хрень я обфускацию не заказывал =\
cresta оптимизация включена - /Ox /Ob1 /O green RTTI отключил, непомогло Ursus там вызов по указателю call User * (UNetworkHandler::*GetUser)(int) т.е. call dword ptr [GetUser]
reverser описание класса в 1м посте могу добавить тольк строчку (FARPROC &)GetUser=GetProcAddress((HMODULE)g_hEngine,UNETWORKHANDLER_GETUSER);
Это особенности работы с pointer-to-member в C++. В данном конкретном случае sizeof(T_GetUser) = 16, а вовсе не 4, как у обычных указателей. Все эти действия действительно нужны для определённых ситуаций для получения корректного указателя this. В данном случае компилятору неизвестно ничего ни о классе UNetworkHandler, ни о указателе GetUser, так что он должен рассматривать разные извращённые ситуации, простейшую из которых демонстрирует пример Код (Text): class UNetworkHandler { public: User* fn1(int a1); }; class Derived : public UNetworkHandler { public: User* fn2(int a1); virtual void somefunction(void); } T_GetUser GetUser1 = &UNetworkHandler::fn1; T_GetUser GetUser2 = static_cast<T_GetUser>&Derived::fn2; ... g_NetworkHandler = new Derived; ... (предлагаю помедитировать над вопросом, где в g_NetworkHandler находятся элементы класса UNetworkHandler и что нужно делать с указателем this класса Derived, чтобы он стал указателем this класса UNetworkHandler).
diamond и как сделать чтобы компилился нормальный код? push [g_UserID] mov ecx, [g_NetworkHandler] call [GetUser]
Так ведь проблема в том, что код Код (Text): push [g_UserID] mov ecx, [g_NetworkHandler] call [GetUser] может быть просто неверен - this для функции [GetUser] может не совпадать с [g_NetworkHandler]. Но если очень хочется, то можно: Код (Text): class __single_inheritance UNetworkHandler;
diamond "class __single_inheritance UNetworkHandler;" спасибо, помогло. я пытаюсь перенести рабочий код с фасма на С++, и хочу чтобы откомпиленный код С++ был не хуже исходного. пока удается с трудом =\