Неверный указатель функции в Visual Studio 2005, код начинается со смещения 1 байт
Рассматриваемый код подключается к проводнику.exe, но был сбой при входе в функцию обратного вызова:
Unhandled exception at 0x60055b50 (redacted.dll) in explorer.exe: 0xC0000005: Access violation writing location 0x548b0cca.
Callstack:
> redacted.dll!myCallWndProcRetCallback(int nCode=0x00000000, unsigned int wParam=0x00000000, long lParam=0x015afa58) Line 799 C++ user32.dll!_DispatchHookW@16() + 0x31 bytes user32.dll!_fnHkINLPCWPRETSTRUCTW@20() + 0x5e bytes user32.dll!___fnDWORD@4() + 0x24 bytes ntdll.dll!_KiUserCallbackDispatcher@12() + 0x13 bytes user32.dll!_NtUserMessageCall@28() + 0xc bytes user32.dll!_SendMessageW@16() + 0x49 bytes explorer.exe!CTaskBand::_FindIndexByHwnd() + 0x21 bytes explorer.exe!CTaskBand::_HandleShellHook() + 0x48 bytes explorer.exe!CTaskBand::v_WndProc() + 0x660 bytes explorer.exe!CImpWndProc::s_WndProc() + 0x3f bytes
Visual Studio 2005 дал следующую дизассемблировку:
--- c:projectsredacted.cpp ------------------------- //------------------------------------------------------------------------------ LRESULT CALLBACK myCallWndProcRetCallback(int nCode, WPARAM wParam, LPARAM lParam) { 60055B50 inc dword ptr [ebx+548B0CC4h] 60055B56 and al,18h 60055B58 mov eax,dword ptr [g_callWndProcRetHook (600B9EE8h)] 60055B5D push esi
И память вокруг 0x548B0CC4-это все ?????? так что это не отображенная память, отсюда и сбой.
Машинный код в начале myCallWndProcRetCallback выглядит следующим образом:0x60055B50: ff 83 c4 0c 8b 54 24 18 a1 e8 9e 0b 60 56 52 57 50 ff 15 8c a6 09 60 5f 5e 83 c4 08 c2 0c 00 cc 8b 4c 24 04 8b 01 8b 50
Но Visual Studio также иногда дает следующую разборку для этого функция:
--- c:projectsredacted.cpp ------------------------- 60055B51 add esp,0Ch if ( nCode == HC_ACTION && lParam != NULL) { 60055B54 mov edx,dword ptr [esp+18h] 60055B58 mov eax,dword ptr [g_callWndProcRetHook (600B9EE8h)] 60055B5D push esi
Это выглядит как правильная разборка, но она начинается на 1 байт позже, чем разборка выше! Вы можете видеть, что инструкции одинаковы с 0x60055B58 и далее.
Итак, похоже, что компоновщик говорит, что функция находится на 0x60055B50, но на самом деле код начинается с 0x60055B51. Я подтвердил, что первый-это обратный вызов, установленный в крюке Windows. Поэтому, когда Windows вызывает обратно в функцию, она выполняет плохой код.
Вопрос, который у меня есть, заключается в том, как линкер может быть, что-то не так? Я сделал перестройку, и проблема ушла, это кажется случайным. В то время параметр /FORCE:MULTIPLE linker был в силе, но без него ошибка связи не сообщается для этого обратного вызова.
Последнее дополнение: может ли это быть связано с переездом или перебазирования библиотеки DLL? Если перемещение было отключено на 1 байт, это, возможно, может вызвать проблему?
1 ответ:
Перемещения почти никогда не будут отключены на 1 байт; образ dll должен быть выровнен по степени детализации выделений, возвращаемых VirtualAlloc, которая должна быть 64k на большинстве машин.
Как долго этот код работал? Если это случайно, то /FORCE: MULTIPLE может быть подозрительным. Или вы можете использовать Incredibuild...