需要更好地理解 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
}
在 win32 中,大多数 API 不会 return 对象作为普通内存。相反,它们通常 return HANDLE
或派生自 IUnknown
的对象实例。要释放与 HANDLE
关联的内存,您通常会调用 CloseHandle
。要释放与 IUnknown
对象关联的内存,请调用 ->Release()
。一些分配需要特殊的发布调用。在您的示例中,由 MapViewOfFile
编辑的指针 return 必须使用 UnmapViewOfFile
.
释放
对于更常见的 win32 对象类型,智能指针包装器在 Microsoft::WRL
库中实现。例如:
Microsoft::WRL::ComPtr<ID3D12Device> spDevice;
D3D12CreateDevice(..., IID_PPV_ARGS(&spDevice));
Microsoft::WRL::Wrappers::FileHandle shFile;
shFile = CreateFile2(...);
spDevice
和 shFile
都将在超出范围时被适当地释放。
对于其他分配,例如 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); });
}
我很难理解智能指针(仍然处于学习的初级阶段)。也许我一直关注这个问题太久了,我错过了简单的概念......
我正在将我所有的 "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
}
在 win32 中,大多数 API 不会 return 对象作为普通内存。相反,它们通常 return HANDLE
或派生自 IUnknown
的对象实例。要释放与 HANDLE
关联的内存,您通常会调用 CloseHandle
。要释放与 IUnknown
对象关联的内存,请调用 ->Release()
。一些分配需要特殊的发布调用。在您的示例中,由 MapViewOfFile
编辑的指针 return 必须使用 UnmapViewOfFile
.
对于更常见的 win32 对象类型,智能指针包装器在 Microsoft::WRL
库中实现。例如:
Microsoft::WRL::ComPtr<ID3D12Device> spDevice;
D3D12CreateDevice(..., IID_PPV_ARGS(&spDevice));
Microsoft::WRL::Wrappers::FileHandle shFile;
shFile = CreateFile2(...);
spDevice
和 shFile
都将在超出范围时被适当地释放。
对于其他分配,例如 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); });
}