Moving semantics and windows. DeleteObject-safe handle?

Is there any kind of NULL handle in Windows? If I create bmp via CreateCompatibleBitmap() and delete it using DeleteObject() and want to use move semantics, I want to make sure that the bitmap is not destroyed. Therefore, I have to set HBITMAP to the value that needs to be deleted. Like delete nullptr .

+4
source share
3 answers

Bad news. For historical reasons, the Windows API usually does not have a valid "invalid handle" value. Various subsystems on Windows consider either NULL or INVALID_HANDLE_VALUE as an invalid descriptor value (both for returning an invalid descriptor value and for accepting it). Related article about Old New Thing .

However, the good news is that although you still need to be prepared for unexpected return values ​​(unless you dig up the documentation for each function you use), providing either an invalid value works "in practice."
You may not have used the correct designated β€œinvalid” value, but it is still invalid and therefore the function will work. Your application will not crash, there are no negative consequences, except for wasted several processor cycles.

So go nullptr and use NULL (or nullptr ), this is good for you. If nothing more, this is intuitive for someone reading your code later. In your specific example, this is also correct, since GDI functions accept NULL as invalid.

You can rely heavily on invalid NULL and INVALID_HANDLE_VALUE values. Although I am not aware of the requirement (as indicated in an explicit statement in the documentation) that a valid HANDLE must be nonzero, in practice they always exist. I bet you won't find a handle with a null value (just try using the Sysinternals HANDLE tool, no process on your computer will probably have a handle below 20).

But even if you assume that NULL may be a valid descriptor value, you must bear in mind that some descriptors are already open and closed before the main call, or global constructors are started, you really have no choice, This means that assuming that NULL may be a valid descriptor, and assuming that it is still in effect at the time your program starts, the likelihood that this hypothetical descriptor accidentally is of a type compatible with the API function is very low.

On the other hand, it can be argued that an application can have (unsigned) -1 handle open, rendering INVALID_HANDLE_VALUE valid value.

If you don’t miss the pens, I can’t imagine how you will ever get a lot of open pens. But more importantly, long before you press this number, you will probably run out of memory on a 64-bit system, and you will end up address space on a 32-bit system.
If INVALID_HANDLE_VALUE , which is a valid handle, ever becomes a problem, you are having a much more serious problem.

+2
source

There is no such safe meaning. Passing anything but a valid HGDIOBJ , in particular, it is a β€œhandle of a logical pen, brush, font, bitmap, region, or palette,” until DeleteObject violates the contract and may cause your program to crash. Or it can break into the debugger, especially with proven OS builds. Or it may populate your hard drive with log messages. Or it can cause AppVerifier to crash and prevent logo certification. Or it may call the "appcompat" rules for your process and disable the new Windows features "for backward compatibility." Do not do that.

You can use 0 as a placeholder, but check the value and not call DeleteObject if your handle is 0 . This is in contrast to if (p) delete p; where the previous test is considered a loss of code.

0
source

Usually 0 is an invalid descriptor similar to nullpointer.

For example, CreateBitmap returns 0 as an invalid bitmap descriptor if it does not work.

Therefore, you can safely call DeleteObject with nullhandle.

From the DeleteObject documentation :

If the specified handle is invalid or is currently selected in DC, the return value is zero.

The exception is the file descriptor returned by CreateFile , where INVALID_HANDLE_VALUE is defined as -1 .

-1
source

All Articles