{"id":94425,"date":"2016-09-30T07:00:00","date_gmt":"2016-09-30T21:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=94425"},"modified":"2019-03-13T11:07:24","modified_gmt":"2019-03-13T18:07:24","slug":"20160930-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20160930-00\/?p=94425","title":{"rendered":"When are global objects constructed and destructed by Visual C++?, redux"},"content":{"rendered":"<p>Today we&#8217;re going to make some clarifications to this table, which came from <a HREF=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20141017-00\/?p=43823\">an earlier article<\/a>: <\/p>\n<table BORDER=\"1\" STYLE=\"border-collapse: collapse\" CELLSPACING=\"0\" CELLPADDING=\"3\">\n<tr>\n<td>When does it run?<\/td>\n<th>Constructor<\/th>\n<th>Destructor<\/th>\n<\/tr>\n<tr>\n<th>Global object in EXE<\/th>\n<td>C runtime startup code<\/td>\n<td>C runtime DLL hired lackey<\/td>\n<\/tr>\n<tr>\n<th>Global object in DLL<\/th>\n<td>C runtime <code>DLL_PROCESS_ATTACH<\/code>     prior to <code>Dll&shy;Main<\/code><\/td>\n<td>C runtime <code>DLL_PROCESS_DETACH<\/code>     after <code>Dll&shy;Main<\/code> returns<\/td>\n<\/tr>\n<\/table>\n<p>It turns out that the upper right corner of the diagram actually splits into two cases. The table lists what happens if the process terminates by calling <code>Exit&shy;Process<\/code>. The thing that makes termination with <code>Exit&shy;Process<\/code> interesting is that the first (and only) time the C runtime library learns about it is when the C runtime library itself receives its <code>DLL_PROCESS_DETACH<\/code> notification, and we saw last time that by the time this notification arrives, <a HREF=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/\">it could very well already be too late<\/a>. <\/p>\n<p>The escape here is to exit the program not by calling <code>Exit&shy;Process<\/code> but rather by calling the C runtime <code>exit<\/code> function. When you do that, the C runtime gets control (by virtue of the fact that you explicitly called it), so it can run down your executable&#8217;s global objects right away, before calling the operating system&#8217;s <code>Exit&shy;Process<\/code> function. That way, the global objects are run down while all of the dependent DLLs are still in memory. <\/p>\n<p>Let&#8217;s update our table: <\/p>\n<table BORDER=\"1\" STYLE=\"border-collapse: collapse\" CELLSPACING=\"0\" CELLPADDING=\"3\">\n<tr>\n<td ROWSPAN=\"2\">When does it run?<\/td>\n<th ROWSPAN=\"2\">Constructor<\/th>\n<th COLSPAN=\"2\">Destructor<\/th>\n<\/tr>\n<tr>\n<th>Ends with exit()<\/th>\n<th>Ends with ExitProcess()<\/th>\n<\/tr>\n<tr>\n<th>Global object in EXE<\/th>\n<td>C runtime startup code<\/td>\n<td>Prior to ExitProcess<\/td>\n<td>C runtime DLL hired lackey<\/td>\n<\/tr>\n<tr>\n<th>Global object in DLL<\/th>\n<td>C runtime <code>DLL_PROCESS_ATTACH<\/code>     prior to <code>Dll&shy;Main<\/code><\/td>\n<td COLSPAN=\"2\">C runtime <code>DLL_PROCESS_DETACH<\/code>     after <code>Dll&shy;Main<\/code> returns<\/td>\n<\/tr>\n<\/table>\n<p>The C and C++ language standards say nothing about what happens if you exit a process by calling some operating system low-level process termination function. Which makes sense, because the C and C++ language standards deal with the standard, not with operating system-specific stuff. I believe that more recent versions of the C runtime library take advantage of this and say, &#8220;You know what? If you exit the process by calling <code>Exit&shy;Process<\/code>, then I&#8217;m simply not going to destruct anything. Serves you right for invoking behavior not covered by the standard.&#8221; In those cases, the upper right corner changes from &#8220;C runtime DLL hired lackey&#8221; to &#8220;never&#8221;. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Adding another column to the table.<\/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-94425","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Adding another column to the table.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/94425","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=94425"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/94425\/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=94425"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=94425"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=94425"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}