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

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

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

DWORD flags =
  GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS;
HMODULE hm = 0;
  ::GetModuleHandleExW(flags, L"Test.dll", &hm);
HRSRC hResource =
  ::FindResourceW(hm, MAKEINTRESOURCEW(TEST1), L"ICON");

if (hResource) {
  HGLOBAL hLoaded = LoadResource(hm, hResource);
  if (hLoaded) {
    size = (int)SizeofResource(hm, hResource);
    auto lpAddress = LockResource(hLoaded);
    //Read resource here
    UnlockResource(hLoaded);
  } else {
    //Error logging
  }
  FreeResource(hLoaded);
} else {
  //Error logging
}

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

struct Deleter {
    void operator()(HMODULE hModule) const
    {
        if (hModule != nullptr)
        {
            FreeLibrary(hModule);
        }
    }
};

using unique_module = std::unique_ptr<std::remove_pointer<HMODULE>::type, Deleter>;


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

HMODULE hm = 0;
unique_module um {hm};

::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(),例如:

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

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

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


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

相关问题