在DllMain中测试调用LoadLibrary和CreateThread函数可正常使用

Feelme

发布日期: 2018-12-20 12:32:15 浏览量: 1126
评分:
star star star star star star star star star star
*转载请注明来自write-bug.com

背景

某天,在网上无意中看到一篇博文,标题是说在DLL的入口点函数DllMain中不能调用 LoadLibrary 加载DLL,因为会造成死锁。看到这里我楞了一下,因为我之前写过很多DLL程序,在入口点函数DllMain中也加载过其它的DLL,从没有出现过什么问题。然后,我便仔细阅读了这篇博文,大概理解了它的意思。它应该想表达的是在DLL的DllMain函数中谨慎使用 LoadLibrary,以防发生死锁情况。

虽然都懂了它的意思,我还是决定自己再亲自动手写一下代码看看。现在,我就把实现的过程和测试心得整理成文档,分享给大家。

实现过程

首先,我直接创建一个名为 Dll_LoadLibrary_CreateThread_Test 的DLL项目工程,在 DllMain 的 DLL_PROCESS_ATTACH 时候直接调用 CreateThread 函数创建一个多线程,同时,也调用 LoadLibrary 加载另一个 DLL 文件。

  1. BOOL APIENTRY DllMain( HMODULE hModule,
  2. DWORD ul_reason_for_call,
  3. LPVOID lpReserved
  4. )
  5. {
  6. switch (ul_reason_for_call)
  7. {
  8. case DLL_PROCESS_ATTACH:
  9. {
  10. // 创建多线程
  11. ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc, NULL, 0, NULL);
  12. // 加载DLL
  13. HMODULE hDll = ::LoadLibrary("testdll.dll");
  14. if (NULL == hDll)
  15. {
  16. ::MessageBox(NULL, "load testdll.dll error.", "error", MB_OK);
  17. }
  18. break;
  19. }
  20. …(省略)
  21. }
  22. return TRUE;
  23. }

其中,ThreadProc 多线程函数,执行的操作就是每个 5000 毫秒就弹窗提示一次。

  1. UINT ThreadProc(LPVOID lpVoid)
  2. {
  3. while (TRUE)
  4. {
  5. Sleep(5000);
  6. ::MessageBox(NULL, "this si from createthread.", "createthread", MB_OK);
  7. }
  8. return 0;
  9. }

在 testdll.dll 这个DLL的入口点函数DllMain中,直接弹窗提示。

  1. BOOL APIENTRY DllMain( HMODULE hModule,
  2. DWORD ul_reason_for_call,
  3. LPVOID lpReserved
  4. )
  5. {
  6. switch (ul_reason_for_call)
  7. {
  8. case DLL_PROCESS_ATTACH:
  9. {
  10. // 弹窗
  11. ::MessageBox(NULL, "this is from testdll.dll DllMain function.", "testdll.dll", MB_OK);
  12. break;
  13. }
  14. …(省略)
  15. }
  16. return TRUE;
  17. }

然后,我们直接加载 Dll_LoadLibrary_CreateThread_Test.dll 文件,成功弹出下图所示的两个提示框,说明 CreateThread 函数成功创建多线程,LoadLibrary 成功加载DLL。

总结

经过上面的例子测试,说明在 DllMain 函数中,是可以使用 CreateThread 以及 LoadLibrary 函数的。只要我们避免相互在 DllMain 中相互调用,出现死锁,如下面这种相互调用的情况:

  • DllB 在 DllMain 里调用 LoadLibrary 加载 DllA

  • DllA 在 DllMain 里调用 LoadLibrary 加载 DllB

这样,就会无限循环加载下去,形成死锁。

所以,之所以说 在DllMain里不能调用LoadLibrary函数,其实,并不是说只要是在 DllMain 中,都不能调用 LoadLibrary 函数,而是说,如果这两个 Dll 如果在 DllMain 中相互调用的情况下,是会出错的,所以,为了避免这种相互调用死锁的情况发生,就不提倡在 DllMain 中调用 LoadLibrary!实际上,只要避免这种相互调用的情况,LoadLibrary 还是可以使用的!

参考

参考自《Windows黑客编程技术详解》一书

上传的附件 cloud_download Dll_LoadLibrary_CreateThread_Test.7z ( 229.61kb, 9次下载 )

发送私信

去奋斗,去追求,去发现,但不要放弃

12
文章数
15
评论数
最近文章
eject