需要更好地理解 windows API 的智能指针

Need a better understanding of smart pointers with windows API

我很难理解智能指针(仍然处于学习的初级阶段)。也许我一直关注这个问题太久了,我错过了简单的概念......

我正在将我所有的 "new/deletes" 变成智能指针,所以我的内存 leaks/corruption 没有这么大的问题。

有了 unique_ptr 你不能只:

PCHAR test;
std::unique_ptr<char[]> buffer = std::make_unique<char[]>(10);
buffer.get() = test;

(如果我错了,请纠正我)因此,我传递一个原始 shared_ptr 来获取我需要查看 PE Headers 的字节地址。 pFileBase 将具有字节 "MZ" 但我的 shared_ptr 不会返回这些字节。我错过了什么?

有没有办法将 WinAPI 函数 return 转换为智能指针? 我也知道我的 shared_ptr 不是 char[],所以这是我修复的下一步。

BOOL InitializeFromDisk(std::wstring &wsTempPath, char *pFileBase)
{
 ...
 pFileBase = (PCHAR)MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
 if (pFileBase == 0) return FALSE;
 return TRUE;
}
int main()
{
 std::shared_ptr<char> pFile = std::make_shared<char>(0);
 InitializeFromDisk(L"c:\...", pFile.get());
 ...
 PIMAGE_DOS_SIGNATURE pDosHdr;
 std::copy(pFile, 2, pDosHdr); //I'm sure this line doesn't quit work yet 
}

中,大多数 API 不会 return 对象作为普通内存。相反,它们通常 return HANDLE 或派生自 IUnknown 的对象实例。要释放与 HANDLE 关联的内存,您通常会调用 CloseHandle。要释放与 IUnknown 对象关联的内存,请调用 ->Release()。一些分配需要特殊的发布调用。在您的示例中,由 MapViewOfFile 编辑的指针 return 必须使用 UnmapViewOfFile.

释放

对于更常见的 对象类型,智能指针包装器在 Microsoft::WRL 库中实现。例如:

Microsoft::WRL::ComPtr<ID3D12Device> spDevice;
D3D12CreateDevice(..., IID_PPV_ARGS(&spDevice));

Microsoft::WRL::Wrappers::FileHandle shFile;
shFile = CreateFile2(...);

spDeviceshFile 都将在超出范围时被适当地释放。

对于其他分配,例如 returned MapViewOfFile 指针,您必须创建自己的智能 pointer/handle class.

我可能会做这样的事情。智能指针具有移动构造函数,因此 return 它们非常有效,并且这样做也会产生更好的代码。请注意 shared_ptr 构造函数中 deleter 参数的使用。

std::shared_ptr<VOID> InitializeFromDisk(const std::wstring& wsTempPath, char *pFileBase)
{
    ...
    auto pMappedFile = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
    if (pMappedFile == nullptr)
    {
        auto lastError = GetLastError();
        throw system_error(lastError, system_category());
    }
    return shared_ptr<VOID>(pMappedFile, [](auto p) { UnmapViewOfFile(p); });
}