{"id":103380,"date":"2020-01-29T07:00:00","date_gmt":"2020-01-29T15:00:00","guid":{"rendered":"http:\/\/devblogs.microsoft.com\/oldnewthing\/?p=103380"},"modified":"2020-01-28T22:36:12","modified_gmt":"2020-01-29T06:36:12","slug":"20200129-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200129-00\/?p=103380","title":{"rendered":"Crashing in COM after I call <CODE>CoUninitialize<\/CODE>, how can COM be running after it is uninitalized?"},"content":{"rendered":"<p>A customer reported that they found a bug in shell32. The customer liaison forwarded the question to the shell team, with the caution that since he is currently on vacation, he hadn&#8217;t validated the legitimacy of the report, or its quality or correctness.<\/p>\n<p>The customer was kind enough to <a href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20131018-00\/?p=2893\"> reduce<\/a> the program to its essence, and that made zeroing in on the problem much easier.<\/p>\n<pre>#import \"shell32.dll\"\r\n\r\n\/\/ Code in italics is wrong\r\n<i>void demonstrate_problem()\r\n{\r\n auto hr = CoInitialize(nullptr);\r\n\r\n  Shell32::IDispatchPtr shell_application(\"Shell.Application\");\r\n\r\n  ... use the shell_application to do stuff ...\r\n\r\n  CoUninitialize();\r\n}<\/i>\r\n<\/pre>\n<p>The customer&#8217;s analysis of the crash was rather lengthy, but hidden inside is this fragment:<\/p>\n<blockquote class=\"q\"><p>If I remove the call to <code>Co\u00adUninitalize<\/code>, then the crash disappears, but from what I understand, I&#8217;m doing everything by the rules. Once I <code>Release<\/code> all the COM pointers I own, I have the right to call <code>Co\u00adUninitialize<\/code>.<\/p><\/blockquote>\n<p>Do you see the problem?<\/p>\n<p>This is another case of paying attention to <a href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20040520-00\/?p=39243\"> when your destructors run<\/a>.<\/p>\n<p>The <code>shell_<\/code><code>application<\/code> object is a smart pointer object, so it will release the raw COM pointer at destruction. When does it destruct?<\/p>\n<p>It destructs <i>after<\/i> the <code>Co\u00adUninitialize<\/code> call.<\/p>\n<p>The customer belived that they had <code>Release<\/code> all of their COM pointers at the point they called <code>Co\u00adUninitialize<\/code>, but in fact they hadn&#8217;t. There was an unreleased COM pointer inside the <code>shell_<\/code><code>application<\/code> object, as well as other objects in the code I elided.<\/p>\n<p>The fix is to ensure that everything is properly released before uninitializing COM. One way is to force the destruction of all relevant objects by introducing a nested scope:<\/p>\n<pre>void demonstrate_problem()\r\n{\r\n auto hr = CoInitialize(nullptr);\r\n\r\n <span style=\"color: blue;\">{ \/\/ nested scope<\/span>\r\n  Shell32::IDispatchPtr shell_application(\"Shell.Application\");\r\n\r\n  ... use the shell_application to do stuff ...\r\n\r\n <span style=\"color: blue;\">} \/\/ force smart objects to destruct<\/span>\r\n CoUninitialize();\r\n}\r\n<\/pre>\n<p>Another is to put the initialize of COM into its own RAII object, so that it destructs last.<\/p>\n<pre>void demonstrate_problem()\r\n{\r\n  <span style=\"color: blue;\"><a href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20040520-00\/?p=39243\">CCoInitialize<\/a> init;<\/span>\r\n\r\n  Shell32::IDispatchPtr shell_application(\"Shell.Application\");\r\n\r\n  ... use the shell_application to do stuff ...\r\n  <span style=\"color: red;\">\/\/ <span style=\"text-decoration: line-through;\">CoUninitialize();<\/span><\/span>\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Mind your destructors.<\/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-103380","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Mind your destructors.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/103380","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=103380"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/103380\/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=103380"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=103380"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=103380"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}