{"id":15623,"date":"2009-12-18T07:00:00","date_gmt":"2009-12-18T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2009\/12\/18\/i-got-an-array-with-plenty-of-nuthin\/"},"modified":"2009-12-18T07:00:00","modified_gmt":"2009-12-18T07:00:00","slug":"i-got-an-array-with-plenty-of-nuthin","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20091218-00\/?p=15623","title":{"rendered":"I got an array with plenty of nuthin&#039;"},"content":{"rendered":"<p>\nA customer reported a memory leak in the function\n<code>PropVariantClear<\/code>:\n<\/p>\n<blockquote CLASS=\"q\">\n<p>\nWe found the following memory leak in the function\n<code>PropVariantClear<\/code>.\nPlease fix it immediately because it causes our program to\nrun out of memory.\n<\/p>\n<p>\nIf the <code>PROPVARIANT<\/code>&#8216;s type is <code>VT_ARRAY<\/code>,\nthen the corresponding <code>SAFEARRAY<\/code> is leaked and not\ncleaned up.\n<\/p>\n<pre>\nSAFEARRAY* psa = SafeArrayCreateVector(VT_UNKNOWN, 0, 1);\nPROPVARIANT v;\nv.vt = VT_ARRAY;\nv.parray = psa;\nPropVariantClear(&amp;v);\n\/\/ The psa is leaked\n<\/pre>\n<p>\nRight now, we are temporarily working around this in our program\nby inserting code before all calls to\n<code>PropVariantClear<\/code> to free the <code>SAFEARRAY<\/code>,\nbut this is clearly an unsatisfactory solution\nbecause it will merely result in double-free bugs once you fix\nthe bug.\nPlease give this defect your highest priority as it is holding up\ndeployment of our system.\n<\/p>\n<\/blockquote>\n<p>\nThe <code>VT_ARRAY<\/code> value is not a variant type in and of itself;\nit is a type <i>modifier<\/i>.\nThere are other type modifiers, such as\n<code>VT_VECTOR<\/code>\nand <code>VT_BYREF<\/code>.\nThe thing about modifiers is that they need to <i>modify something<\/i>.\n<\/p>\n<blockquote CLASS=\"m\"><p>\nThe line\n<code>v.vt = VT_ARRAY<\/code> is incorrect.\nYou have to say what you have a safe array <i>of<\/i>.\nIn this case, you want <code>v.vt = VT_ARRAY | VT_UNKNOWN<\/code>.\nOnce you change that, you&#8217;ll find the memory leak is fixed.\n<\/p><\/blockquote>\n<p>\nThe customer didn&#8217;t believe this explanation.\n<\/p>\n<blockquote CLASS=\"q\">\n<p>\nI find this doubtful for several reasons.\n<\/p>\n<ol>\n<li>While this would explain why the\n    <code>IUnknown<\/code>s in the <code>SAFEARRAY<\/code>\n    are not released,\n    it doesn&#8217;t explain why the <code>SAFEARRAY<\/code> itself is leaked.<\/p>\n<li>The <code>SAFEARRAY<\/code> already contains this information,\n    so it should already know that destroying it entails releasing\n    the <code>IUnknown<\/code> pointers.<\/p>\n<li>If I manually call <code>SafeArrayDestroy<\/code>,\n    then the <code>IUnknown<\/code>s are correctly\n    released, confirming point&nbsp;2.<\/p>\n<li>The function <code>SafeArrayDestroy<\/code> is never called;\n    that is the root cause of the problem.\n<\/ol>\n<\/blockquote>\n<p>\nThe customer&#8217;s mental model of <code>PropVariantDestroy<\/code>\nappeared to be that it should go something like this:\n<\/p>\n<pre>\nif (pvt-&gt;vt &amp; VT_ARRAY) {\n switch (pvt-&gt;vt &amp; VT_TYPEMASK) {\n ...\n case VT_UNKNOWN:\n  ... release the IUnknowns in the SAFEARRAY...\n  break;\n ...\n }\n InternalFree(pvt-&gt;psa-&gt;pvData);\n InternalFree(pvt-&gt;psa);\n return S_OK;\n}\n<\/pre>\n<p>\nIn fact what&#8217;s really going on is that the value of\n<code>VT_ARRAY<\/code> is interpreted as\n<code>VT_ARRAY | VT_EMPTY<\/code>,\nbecause (1)&nbsp;<code>VT_ARRAY<\/code> is a modifier,\nso it has to modify something, and (2)&nbsp;the\nnumeric value of zero happens to be equal to <code>VT_EMPTY<\/code>.\nIn other words, you told OLE automation that your <code>PROPVARIANT<\/code>\nholds a <code>SAFEARRAY<\/code> filled with <code>VT_EMPTY<\/code>.\n<\/p>\n<p>\nIt also happens that a <code>SAFEARRAY<\/code> of <code>VT_EMPTY<\/code>\nis illegal.\nOnly certain types can be placed in a <code>SAFEARRAY<\/code>,\nand <code>VT_EMPTY<\/code> is not one of them.\n<\/p>\n<p>\nThe call to <code>PropVariantClear<\/code> was returning the\nerror\n<code>DISP_E_BADVARTYPE<\/code>.\nIt was performing parameter validation and rejecting the property\nvariant as invalid,\nbecause you can&#8217;t have an array of nothing.\nThe customer&#8217;s response to this explanation was very terse.\n<\/p>\n<blockquote CLASS=\"q\"><p>\nTx. Interesting.\n<\/p><\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>A customer reported a memory leak in the function PropVariantClear: We found the following memory leak in the function PropVariantClear. Please fix it immediately because it causes our program to run out of memory. If the PROPVARIANT&#8216;s type is VT_ARRAY, then the corresponding SAFEARRAY is leaked and not cleaned up. SAFEARRAY* psa = SafeArrayCreateVector(VT_UNKNOWN, 0, [&hellip;]<\/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-15623","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>A customer reported a memory leak in the function PropVariantClear: We found the following memory leak in the function PropVariantClear. Please fix it immediately because it causes our program to run out of memory. If the PROPVARIANT&#8216;s type is VT_ARRAY, then the corresponding SAFEARRAY is leaked and not cleaned up. SAFEARRAY* psa = SafeArrayCreateVector(VT_UNKNOWN, 0, [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/15623","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=15623"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/15623\/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=15623"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=15623"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=15623"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}