windows 使用unique_ptr调用::GetModuleHandleEx,该函数具有自定义删除器以自动处理释放资源

zxlwwiss  于 2023-11-21  发布在  Windows
关注(0)|答案(1)|浏览(197)

我需要释放下面代码中的HMODULE吗?

  1. DWORD flags =
  2. GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS;
  3. HMODULE hm = 0;
  4. ::GetModuleHandleExW(flags, L"Test.dll", &hm);
  5. HRSRC hResource =
  6. ::FindResourceW(hm, MAKEINTRESOURCEW(TEST1), L"ICON");
  7. if (hResource) {
  8. HGLOBAL hLoaded = LoadResource(hm, hResource);
  9. if (hLoaded) {
  10. size = (int)SizeofResource(hm, hResource);
  11. auto lpAddress = LockResource(hLoaded);
  12. //Read resource here
  13. UnlockResource(hLoaded);
  14. } else {
  15. //Error logging
  16. }
  17. FreeResource(hLoaded);
  18. } else {
  19. //Error logging
  20. }

字符串
在这里,我在正确的位置释放了大部分资源,除了可能的HMODULE!我需要释放hm吗?我的理解是,我们只得到HMODULE,而不是在这里加载库,所以我们可能不需要释放它?
如果答案是肯定的,那么我想尝试一下我们在这里所做的事情:
Using std::unique_ptr for Windows HANDLEs

  1. struct Deleter {
  2. void operator()(HMODULE hModule) const
  3. {
  4. if (hModule != nullptr)
  5. {
  6. FreeLibrary(hModule);
  7. }
  8. }
  9. };
  10. using unique_module = std::unique_ptr<std::remove_pointer<HMODULE>::type, Deleter>;


但是我有点困惑,比如如何使用这个unique_module
与此同时,我正在写:

  1. HMODULE hm = 0;
  2. unique_module um {hm};
  3. ::GetModuleHandleExW(flags, L"Test.dll", &um.get());


虽然我没有编译和测试,但这对我来说似乎是错误的,我需要输入如何正确编写这个自定义删除器并将其与HMODULE一起使用,以及如何使用::GetModuleHandleEx()调用它。

anhgbhbe

anhgbhbe1#

首先,你使用GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS是错误的,因为你没有给GetModuleHandleExW()传递一个你正在寻找的模块内部的内存地址。如果你想通过它的名字找到一个模块,那么不要使用GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS。在这种情况下,你可以直接使用GetModuleHandleW(),而不用担心FreeLibrary()
话虽如此
为了回答你的实际问题,GetModuleHandleExW()文档说:
https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandleexw
检索指定模块的模块句柄并递增模块的引用计数,除非指定了GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT。模块必须已由调用进程加载。
...
[in] dwFlags
此参数可以是零或以下值中的一个或多个。如果模块的引用计数递增,则调用者必须使用FreeLibrary函数在不再需要模块句柄时递减引用计数
所以是的,如果你没有使用GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,你需要调用FreeLibrary(),例如:

  1. HMODULE hm = NULL;
  2. ::GetModuleHandleExW(0, L"Test.dll", &hm);
  3. ...
  4. FreeLibrary(hm);

字符串
如果你想使用unique_ptr和一个自定义的Deleter来调用FreeLibrary(),这当然是可行的,但是你不能获得unique_ptr所持有的指针的地址,所以你必须在从它构造unique_ptr之前 * 检索HMODULE,例如:

  1. HMODULE hm = NULL;
  2. ::GetModuleHandleExW(0, L"Test.dll", &hm);
  3. unique_module um {hm};


否则,您可以简单地忘记Deleter,如果必须使用GetModuleHandleExW(),则使用GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,或者仅使用GetModuleHandleW()

展开查看全部

相关问题