{"id":94405,"date":"2016-09-28T07:00:00","date_gmt":"2016-09-28T21:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=94405"},"modified":"2019-03-13T11:07:18","modified_gmt":"2019-03-13T18:07:18","slug":"20160928-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20160928-00\/?p=94405","title":{"rendered":"When can you free the memory backing the HSTRING you created with WindowsCreateStringReference?"},"content":{"rendered":"<p>A little while back, I posted <a HREF=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20160615-00\/?p=93675\">my complete guide to HSTRING semantics<\/a> (a rip-off of <a HREF=\"https:\/\/blogs.msdn.microsoft.com\/ericlippert\/2003\/09\/12\/erics-complete-guide-to-bstr-semantics\/\">Eric&#8217;s complete guide to BSTR semantics<\/a>). A discussion of security descriptor lifetime somehow triggered the question &#8220;<a HREF=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/#comment-1249765\">When can you free the memory backing the <code>HSTRING<\/code> you created with <code>Windows&shy;Create&shy;String&shy;Reference<\/code><\/a>?&#8221; <\/p>\n<p>You can free the memory backing the <code>HSTRING<\/code> after you destroy the <code>HSTRING<\/code>, and since this is a fast-pass string, you destroy the <code>HSTRING<\/code> by simply abandoning it. Therefore, you can free the memory when you know that nobody should have a copy of the fast-pass <code>HSTRING<\/code> handle any more. <\/p>\n<p>(For the purpose of terminology, I&#8217;m going to say that you have a &#8220;copy&#8221; of an <code>HSTRING<\/code> handle if you merely copied the <code>HSTRING<\/code> handle. E.g., <code>HSTRING copy = hstr;<\/code> On the other hand, I&#8217;m going to say that you have a &#8220;duplicate&#8221; of an <code>HSTRING<\/code> if you passed it to <code>Windows&shy;Duplicate&shy;String<\/code>.) <\/p>\n<p>Okay, so how do you know that nobody has a copy of the fast-pass <code>HSTRING<\/code> handle any more? <\/p>\n<p>Recall the rules for <code>HSTRING<\/code>s: If a function is passed an <code>HSTRING<\/code> and it wants to save the <code>HSTRING<\/code> for future use, it must use <code>Windows&shy;Duplicate&shy;String<\/code> to increment the reference count on the string (and possibly convert it from fast-pass to standard). Therefore, if you pass the <code>HSTRING<\/code> to another function, you know that there are no copies of that <code>HSTRING<\/code> handle when the function returns, because creating a copy is not allowed. The only place where a literal copy of the <code>HSTRING<\/code> handle is allowed is in the function that created it, and therefore you know when there are no more copies of the <code>HSTRING<\/code> handle because all of the copies belong to you. <\/p>\n<p>The question sort of acknowledges this rule, but notes, &#8220;All it takes is one bug somewhere in all of WinRT where someone forgets to duplicate a input string if they need said string later after the function has returned.&#8221; <\/p>\n<p>That&#8217;s true. But it&#8217;s true of C-style string pointers, too! If you pass a C-style string to another function, and that other function wants to retain the string, it&#8217;s going to need to call <code>strdup<\/code> or some other string duplication function so it can have its own private copy of the string. The value received as a function parameter is not valid once the function returns; if you need to use it after the function returns, you need to duplicate the string. <\/p>\n<p>Similarly, if you receive a COM interface pointer, and you want to continue using it after the function returns, you need to call <code>IUnknown::AddRef<\/code> to increase the reference count on the interface, corresponding to the copy of the pointer you retained. When you&#8217;re done with the pointer, you call <code>IUnknown::Release<\/code>. <\/p>\n<p>In both of these cases, you are relying on people writing code to respect these rules. All it takes is one bug somewhere in all of C where someone forgets to duplicate a input string if they need said string later after the function has returned. <\/p>\n<p>Somehow, we&#8217;ve managed to survive working with C-style strings and with COM interface pointers with these rules. Maybe it&#8217;s with the help of things like smart pointers, or maybe it&#8217;s just through good discipline. Whatever the reason, keep up the good work. <\/p>\n<p><b>Bonus chatter<\/b>: One of the rules for fast-pass strings is that you cannot change the contents of the string as long as the <code>HSTRING<\/code> is still in use. One commenter interpreted this to mean that string references aren&#8217;t thread-safe. Not true. Rather, the statement is a direct reflection of the fact that an <code>HSTRING<\/code> is immutable. If you changed the contents of the buffer that backs the <code>HSTRING<\/code>, then you break the immutability rule. Thread safety is not at issue here. You can use a fast-pass string from any thread you like, as long as you stop using it before your function returns. (This means that your function cannot return until the other thread has definitely finished with the fast-pass string. In practice, this is not commonly done; instead, the function uses <code>Windows&shy;Duplicate&shy;String<\/code> to create a standard <code>HSTRING<\/code> and passes that <code>HSTRING<\/code> to the other thread, which can then <code>Windows&shy;Delete&shy;String<\/code> the <code>HSTRING<\/code> when it is done.) <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Nothing you haven&#8217;t had to deal with already.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-94405","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Nothing you haven&#8217;t had to deal with already.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/94405","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=94405"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/94405\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=94405"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=94405"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=94405"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}