FreeLibraryAndExitThread аварийно завершает работу программы при выгрузке внедренной DLL

Я пишу DLL, которая вводится в игру, чтобы поиграть с реверс-инжинирингом. Некоторое время я мог успешно вводить, извлекать и повторно вводить, когда вносил изменения в программу. я использую FreeLibraryAndExitThread разгрузить.

После добавления XInput в программу, чтобы я мог перехватить ввод пользователя, игра вылетает с нарушением прав доступа при вызове FreeLibraryAndExitThread, Исходя из этого поста, я предполагаю, что использование XInput оставляет что - то "живое" в программе, когда я выхожу на выгрузку, и именно это вызывает сбой. Я, честно говоря, в растерянности, как это исправить.

Вот код, который вылетает из программы при выходе:

    XINPUT_STATE state;
    ZeroMemory(&state, sizeof(XINPUT_STATE));

    //The problematic line of code
    bool gamepad = XInputGetState(0, &state) == ERROR_SUCCESS; 

    WORD buttonsHeld = state.Gamepad.wButtons;
    WORD buttonsPressed = (~previousButtonState) & state.Gamepad.wButtons;
    WORD buttonsReleased = previousButtonState & (~state.Gamepad.wButtons);

Когда я удаляю звонок XInputGetState все работает отлично, и я могу выгрузить DLL без сбоев.

И вот как я призываю программу выгрузить и выйти

    FreeLibraryAndExitThread(hDLL, 0);

куда hDLL это аргумент hinstDLL от DllMain, Я также пытался GetModuleHandleEx Вместо того, чтобы использовать hinstDLL,

Я думаю, что либо:

  • С помощью XInputGetState заставляет мою программу загружать вторую DLL для XInput, или же

  • XInputGetState создает какую-то ссылку на мою DLL при вызове, а когда я удаляю свою DLL, она пытается получить доступ к памяти, которой больше нет.

РЕДАКТИРОВАТЬ: я немного копать, и проблема, кажется, заключается в том, что добавление вызова XInputGetState заставляет мою DLL загружаться XINPUT1_4.dll, Я пытался с помощью FreeLibrary разгрузить его, но это не работает.

РЕДАКТИРОВАТЬ: я сузил его еще немного - оказывается, что нарушение прав доступа вызвано тем, что какой-то поток в игре пытается вернуться к части кода XINPUT1_4.dll, которая выгружается, что приводит к сбою. И я понятия не имею, как это исправить.

Окончательное редактирование: это было простое исправление, мне пришлось позвонить LoadLibrary(L"XINPUT1_4.dll") для DLL, которая была причиной проблемы.

1 ответ

Вот решение:

Проблема заключалась в том, что XInputGetState заставил мою DLL автоматически загружаться XINPUT1_4.dllи когда я вызвал FreeLibraryAndExitThread, моя выгрузка DLL заставила также выгружать DLL XInput. Код внутри программы (вероятно, из потока в XInput 1.4) попытался выполнить код, которого больше не было, что вызвало нарушение прав доступа.

Таким образом, решение было просто позвонить LoadLibrary(L'XINPUT1_4.dll') после того, как я инициализирую поток моей DLL, так что когда моя DLL выгружается, DLL XInput остается в памяти, потому что LoadLibrary увеличивает счетчик ссылок.

(Когда счетчик ссылок DLL достигает 0, он выгружается. При первой загрузке он инициализируется как 1, LoadLibrary увеличивает его на 1, а вызов FreeLibraryAndExitThread уменьшает его на 1. Поэтому, когда все сказано и сделано, счетчик ссылок выше 0 и он остается в памяти, так как моя DLL выгружается)

Другие вопросы по тегам