{"id":39243,"date":"2004-05-20T10:00:00","date_gmt":"2004-05-20T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2004\/05\/20\/do-you-know-when-your-destructors-run-part-1\/"},"modified":"2004-05-20T10:00:00","modified_gmt":"2004-05-20T10:00:00","slug":"do-you-know-when-your-destructors-run-part-1","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20040520-00\/?p=39243","title":{"rendered":"Do you know when your destructors run? Part 1."},"content":{"rendered":"<p>\n<a href=\"http:\/\/blogs.msdn.com\/LarryOsterman\/archive\/2004\/04\/22\/118240.aspx\">\nLarry Osterman discussed the importance of knowing when your\nglobal destructors run<\/a>, but this problem is not exclusive\nto global objects.  You need to take care even with local\nobjects.  Consider:\n<\/p>\n<pre>\nvoid Sample()\n{\n  if (SUCCEEDED(CoInitialize(NULL))) {\n    CComPtr&lt;IXMLDOMDocument&gt; p;\n    if (SUCCEEDED(p.CoCreateInstance(CLSID_IXMLDOMDocument))) {\n     ...\n    }\n    CoUninitialize();\n  }\n}\n<\/pre>\n<p>\nEasy as pie.  And there&#8217;s a bug here.\n<\/p>\n<p>\nWhen does the destructor for that smart-pointer run?\n<\/p>\n<p>\nAnswer: When the object goes out of scope,\nwhich is at the closing brace of the outer <code>if<\/code> statement,\n<strong>after<\/strong> the <code>CoUninitialize<\/code> call.\n<\/p>\n<p>\nSo you shut down COM, and then try to access a pointer to a COM object.\nThis is not good.\n(Or as Larry describes it, &#8220;Blam!&#8221;)\n<\/p>\n<p>\nTo fix this problem, you have to release all your COM pointers\nbefore the <code>CoUninitialize<\/code>.  One way would be to insert a\n<code>p.Release()<\/code> at the end of the inner <code>if<\/code>.\n(But of course, if you&#8217;re going to do that, then why bother using\na smart pointer?)\n<\/p>\n<p>\nAnother fix would be to introduce a seemingly unnecessary scope:\n<\/p>\n<pre>\nvoid Sample()\n{\n  if (SUCCEEDED(CoInitialize(NULL))) {\n    {\n      CComPtr&lt;IXMLDOMDocument&gt; p;\n      if (SUCCEEDED(p.CoCreateInstance(CLSID_IXMLDOMDocument))) {\n       ...\n      }\n    } <font COLOR=\"blue\">\/\/ ensure p is destructed before the CoUninit<\/font>\n    CoUninitialize();\n  }\n}\n<\/pre>\n<p>\nMake sure you leave that comment there or the next person to come\nacross this code is going to &#8220;clean it up&#8221; by removing the\n&#8220;redundant&#8221; braces.\n<\/p>\n<p>\nOf course, this is still too subtle.  Here&#8217;s another solution:\nPut the CoUninitialize inside a destructor of its own!\n<\/p>\n<pre>\nclass CCoInitialize {\npublic:\n CCoInitialize() : m_hr(CoInitialize(NULL)) { }\n ~CCoInitialize() { if (SUCCEEDED(m_hr)) CoUninitialize(); }\n operator HRESULT() const { return m_hr; }\n HRESULT m_hr;\n};\nvoid Sample()\n{\n  CCoInitialize init;\n  if (SUCCEEDED(init)) {\n    CComPtr&lt;IXMLDOMDocument&gt; p;\n    if (SUCCEEDED(p.CoCreateInstance(CLSID_IXMLDOMDocument))) {\n     ...\n    }\n  }\n} <font COLOR=\"blue\">\/\/ CoUninitialize happens here<\/font>\n<\/pre>\n<p>\nThis works even if you put the smart pointer at the same scope,\nas long as you put it <strong>after the CCoInitialize object<\/strong>:<\/p>\n<pre>\nvoid Sample()\n{\n  CCoInitialize init;\n  CComPtr&lt;IXMLDOMDocument&gt; p;\n  if (SUCCEEDED(init) &amp;&amp;\n      SUCCEEDED(p.CoCreateInstance(CLSID_IXMLDOMDocument))) {\n   ...\n  }\n}\n<\/pre>\n<p>\nThis works because objects with automatic storage duration\nare destructed in reverse order of declaration, so the\nobject <code>p<\/code> wil be destructed first, then the\nobject <code>init<\/code>.\n<\/p>\n<p>\nMind you, this is basically subtle no matter now you slice it.\nNobody said programming was easy.\n<\/p>\n<p>\nTomorrow, part 2.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Larry Osterman discussed the importance of knowing when your global destructors run, but this problem is not exclusive to global objects. You need to take care even with local objects. Consider: void Sample() { if (SUCCEEDED(CoInitialize(NULL))) { CComPtr&lt;IXMLDOMDocument&gt; p; if (SUCCEEDED(p.CoCreateInstance(CLSID_IXMLDOMDocument))) { &#8230; } CoUninitialize(); } } Easy as pie. And there&#8217;s a bug here. [&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-39243","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Larry Osterman discussed the importance of knowing when your global destructors run, but this problem is not exclusive to global objects. You need to take care even with local objects. Consider: void Sample() { if (SUCCEEDED(CoInitialize(NULL))) { CComPtr&lt;IXMLDOMDocument&gt; p; if (SUCCEEDED(p.CoCreateInstance(CLSID_IXMLDOMDocument))) { &#8230; } CoUninitialize(); } } Easy as pie. And there&#8217;s a bug here. [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/39243","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=39243"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/39243\/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=39243"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=39243"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=39243"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}