我正在编写一个 DLL,该 DLL 被注入(inject)到游戏中以便进行一些逆向工程。有一段时间,当我对程序进行更改时,我能够成功地注入(inject)、弹出和重新注入(inject)。我正在使用 FreeLibraryAndExitThread
卸载。
在将 XInput 添加到程序中以便我可以捕获用户输入后,当我调用 FreeLibraryAndExitThread
时,游戏因访问冲突而崩溃。来自 this post ,我猜想当我去卸载时,使用 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
是 DllMain
的参数 hinstDLL
。我还尝试了 GetModuleHandleEx
而不是使用 hinstDLL
。
我的猜测是:
使用
XInputGetState
使我的程序为XInput
加载第二个 DLL,或者XInputGetState
在调用时创建对我的 DLL 的某种引用,当我删除我的 DLL 时,它会尝试访问不再存在的内存。
编辑:我做了一些挖掘,问题似乎是添加对 XInputGetState
的调用会导致我的 DLL 加载 XINPUT1_4.dll
。我尝试使用 FreeLibrary
卸载它,但它不起作用。
编辑:我进一步缩小了它的范围 - 事实证明,访问冲突是由游戏中的某个线程试图返回到已卸载的 XINPUT1_4.dll 代码的一部分引起的,导致它崩溃。我不知道如何解决这个问题。
最终编辑:这是一个简单的修复,我必须为导致问题的 DLL 调用 LoadLibrary(L"XINPUT1_4.dll")
。
最佳答案
解决方法如下:
问题是调用 XInputGetState
导致我的 DLL 自动加载 XINPUT1_4.dll
,当我调用 FreeLibraryAndExitThread 时,我的 DLL 卸载也强制卸载 XInput DLL .程序中的代码(可能来自 XInput 1.4 中的线程)试图执行不再存在的代码,从而导致访问冲突。
所以解决方案就是在我初始化 DLL 的线程后简单地调用 LoadLibrary(L'XINPUT1_4.dll')
,这样当我的 DLL 被卸载时,XInput DLL 会保留在内存中,因为 LoadLibrary
增加引用计数。
(当一个 DLL 的引用计数达到 0 时,它会卸载。当你第一次加载它时它被初始化为 1,LoadLibrary 将它递增 1,调用 FreeLibraryAndExitThread 将它递减 1。所以当一切都说完了,它的引用计数大于 0,并且在卸载我的 DLL 时它保留在内存中)
关于c++ - 卸载注入(inject)的 DLL 时,FreeLibraryAndExitThread 使程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39780590/