You can’t give away something that isn’t yours


This rule of real life applies to code as well. If something doesn’t belong to you, then you can’t give it away.

For example, functions like SetCliboardData and SetWindowRgn take ownership of the item that you pass it. In SetClipboardData's case, the memory block you pass as the hMem parameter becomes the property of the clipboard. For SetWindowRgn it's the hRgn that becomes the property of the window manager. In both cases, you are giving control of the item to another component, but in order to do that legitimately, it must be yours to give away.

This statement may be obvious, but it's surprising how many people fail to grasp its consequences. For example, you can't do this:

// error checkin removed to improve readability
SetClipboardData(CF_TEXT, hMem);
// Code in italics is wrong
SetClipboardData(RegisterClipboardData(CFSTR_SHELLURL), hMem);

Once you call SetClipboardData the first time, the memory now belongs to the clipboard; it's not yours again. When you call SetClipboardData a second time, you're giving it away again, but the second time, it's not your memory any more.

In other words: After the first call to SetClipboardData, the memory belongs to the clipboard. The second call is trying to give away something that you no longer own.

It reminds me of a news story I read some time ago. In the United States, the winner of a major lottery often gets a choice between a series of payments over several years or a lump sum. Somebody won the lottery and agreed to sell the annuity to a company in exchange for a lump sum. (Presumably, this company offered a lump sum larger than the one offered by the lottery.) And then when the lottery asked whether to disburse the winnings in the form of an annuity or a lump sum, the winner opted for the lump sum. Dude, you can't take the lump sum. You already sold the revenue stream to that other company. That's not your money any more.

Comments (13)
  1. waleri says:

    It would be much less confusing, if the rule applies in all cases. In WM_SETFONT I do exactly the same, yet the documentation says "application should call the DeleteObject function to delete the font when it is no longer needed; for example, after it destroys the control."

    So do I give it away or not?

    How to know when do you give it away and when you don’t?

  2. John says:

    Give it away, give it away, give it away now.

  3. Brian says:

    waleri, check MSDN:

    For SetClipboardData():

    "If SetClipboardData succeeds, the system owns the object identified by the hMem parameter. The application may not write to or free the data once ownership has been transferred to the system"

    For WM_SETFONT:

    "The application should call the DeleteObject function to delete the font when it is no longer needed"

    Generally, if the documentation says you give it away, then you do.  If the documentation says you do not, then you don’t.

  4. Yuhong Bao says:

    "After the first call to SetClipboardData, the memory belongs to the clipboard. "

    You can’t share memory across processes in Win32 like you do in Win16, which means that the handle is probably freed by the time SetClipboardData returned

  5. BryanK says:

    Or, more specifically, if the documentation says that you have to free, or delete, or otherwise clean up after the object, then you still own it.  (Since that’s what ownership is, at least most of the time: the responsibility to clean up after whatever object is being discussed.)

    If the docs don’t say anything at all about who cleans up after the object (this is rare; I’ve only ever seen one instance), then I’m not sure.  I would *guess* that you still own it.

    (Yes, I’d agree that it would be less confusing if the docs always explicitly called out whether you were giving away any pointed-to object (including HANDLEs) or not, for any API.  But on the other hand, it would be a huge pain to go back through every single API call and annotate each pointer-or-HANDLE parameter with that information.  I’d guess it probably isn’t worth it, as long as the few cases where the information is missed get fixed quickly.)

  6. Julian says:

    Re the lottery: are you *absolutely* sure?

    Perhaps the contract with the annuity company merely required the winner to pay them the winning amount each year, rather than the *actual* winnings.

    In other words, provided the winner made arrangements to invest the lump sum from the lottery and then pay the correct amount to the annuity ompany each year (from another annuity (?!), bank interest, or  investment income), it might all be above board.

    Of course, I can’t see why any sane annuity company would do this – since they need to make a profit, one would expect their lump sum to be less than that available from the lottery who have already made a profit from all the losers).

    The only explanation I can think of is strange tax laws that make this sort of arrangement worthwhile.

    [Well, yeah, if you can cough up the money some other way, then go for it. But I bet you don’t. -Raymond]
  7. waleri says:

    @Brian

    I am aware of that.

    All I am saying is, that it is confusing, since you have to check documentation for each function that sets something. Life would be much easier if there were logic to follow. Now where is that time machine…

  8. Roman says:

    Um, what is RegisterClipboardData? From the looks of it, you might have meant RegisterClipboardFormat instead.

  9. Raymond, the belief that "If something doesn’t belong to you, then you can’t give it away." is in fact an application of US/UK law that does not hold everywhere.

    If you give someone a gift in France (like money) then the gifter has the right to revert that gift if the recipient commits some particularly outrageous act, like trying to kill the gifter.

    So: in a french OS, it would be OK to give away data you gave to the clipboard, but only if the clipboard did something malicious to you first.

  10. Mike Dimmick says:

    That’s terrible documentation on WM_SETFONT. What it should say is that the font object you pass in the WM_SETFONT message must last as long as the control does, that is, you must not destroy it until either a) you’ve destroyed the control or b) you set a different font.

    The reason is that the control will blindly pass the handle to SelectObject when handling WM_PAINT and if the handle no longer points to anything, or points to something that isn’t a font, you get very weird results.

    I’ve added Community Content to this effect.

  11. AndyB says:

    Re: the lottery.

    Its more likely that the winner thought he had a lumpsum *and* an annuity, and decided to sell the unwanted annuity for a pile of cash to add to his other pile of cash winnings.

  12. Carter says:

    So is the moral, plagiarize the memory and give away the pirated memory.

  13. Get the owner to share it with you.

Comments are closed.