简体   繁体   中英

Need a better understanding of smart pointers with windows API

I'm having a hard time understanding smart pointers (still in the beginning stages of learning tbh). Maybe I've been starring at the problem too long and I'm missing the easy concept...

I'm in the process of turning all my "new/deletes" into smart pointers so I don't have such a big issue with memory leaks/corruption.

With unique_ptr's you can't just:

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

(Please correct me if I'm wrong) So instead, I'm passing a raw shared_ptr to get the address of bytes I need to look into PE Headers. pFileBase will have the bytes "MZ" but my shared_ptr is not coming back with those bytes. What am I missing?

Is there a way to have WinAPI functions return into a smart pointer? I'm also aware my shared_ptr is not char[] so that is my next step on fixing.

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 
}

I might do something like this. Smart pointers have move constructors, so it's pretty efficient to return them, and doing so also yields better code. Note the use of the deleter argument in the shared_ptr constructor.

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); });
}

In , most APIs do not return objects as plain memory. Instead, they usually return either HANDLE s or object instances that derive from IUnknown . To free the memory associated with a HANDLE , you will usually call CloseHandle . To free the memory associated with an IUnknown object, call ->Release() . Some allocations require special release calls. In your example, the pointer returned by MapViewOfFile must be deallocated with UnmapViewOfFile .

For the more common types of objects, smart pointer wrappers are implemented in the Microsoft::WRL library. For example:

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

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

Both spDevice and shFile will be appropriately deallocated upon going out of scope.

For other allocations, like the returned MapViewOfFile pointer, you'll have to create your own smart pointer/handle class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM