Documentation about GlobalLock says:
Return value
If the function succeeds, the return value is a pointer to the first byte of the memory block.
If the function fails, the return value is NULL. To get extended error information, call GetLastError.Remarks
Each successful call that a process makes to GlobalLock for an object must be matched by a corresponding call to GlobalUnlock.
....
If the specified memory block has been discarded or if the memory block has a zero-byte size, this function returns NULL.
So, as we see, GlobalLock()
could return NULL if error or memory block size has zero-byte size.
On the other hand, GlobalUnlock()
should be called ONLY if GlobalLock()
was successful. So, how correctly define case when GlobalUnlock() should be called? What approach is correct from following variants and why?
Variant 0:
HGLOBAL hMem = /*some handle on global memory block*/;
// lock block
auto pMem = static_cast<LPBYTE>(::GlobalLock(hMem));
if (pMem!=nullptr)
{
// ... work with pMem
}
// call unlock in any case
::GlobalUnlock(hMem);
Variant 1:
HGLOBAL hMem = /*some handle on global memory block*/;
// lock block
auto pMem = static_cast<LPBYTE>(::GlobalLock(hMem));
if (pMem!=nullptr)
{
// ... work with pMem
// unlock block
::GlobalUnlock(hMem);
}
Variant 2:
HGLOBAL hMem = /*some handle on global memory block*/;
// lock block
auto pMem = static_cast<LPBYTE>(::GlobalLock(hMem));
auto isMemLocked = (pMem!=nullptr);
if (isMemLocked)
{
// ... work with pMem
}
else
{
// is it real error?
isMemLocked = ::GetLastError()==NOERROR;
}
if (isMemLocked)
{
// unlock block
::GlobalUnlock(hMem);
}
Update: We assume that hMem is valid (handle is not NULL).
P.S.: Great thanks for your answers.
global_locker
that takes in anHGLOBAL
– Mgetz