{"id":25573,"date":"2007-08-15T10:00:00","date_gmt":"2007-08-15T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2007\/08\/15\/c-static-constructors-are-called-on-demand-not-at-startup\/"},"modified":"2007-08-15T10:00:00","modified_gmt":"2007-08-15T10:00:00","slug":"c-static-constructors-are-called-on-demand-not-at-startup","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20070815-00\/?p=25573","title":{"rendered":"C# static constructors are called on demand, not at startup"},"content":{"rendered":"<p>\nOne of the differences between C++ and C# is when static constructors run.\nIn C++, static constructors are the first thing run in a module,\neven before the <code>DllMain<\/code> function\nruns.&sup1;\nIn C#, however, static constructors\n<a HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/csspec\/html\/vclrfcsharpspec_10_11.asp\">\ndon&#8217;t run until you use the class for the first time<\/a>.\nIf your static constructor has side effects,\nyou may find yourself experiencing those side effects in strange ways.\n<\/p>\n<p>\nConsider the following program.\nIt&#8217;s rather contrived and artificial,\nbut it&#8217;s based on an actual program that encountered the same problem.\n<\/p>\n<pre>\nusing System;\nusing System.Runtime.InteropServices;\nclass Program {\n [DllImport(\"kernel32.dll\", SetLastError=true)]\n public static extern bool SetEvent(IntPtr hEvent);\n public static void Main()\n {\n  if (!SetEvent(IntPtr.Zero)) {\n   System.Console.WriteLine(\"Error: {0}\", Trace.GetLastErrorFriendlyName());\n  }\n }\n}\n<\/pre>\n<p>\nThis program tries to set an invalid event, so the call to\n<code>SetEvent<\/code> is expected to fail with an invalid handle error.\nWe print the last error code using a function in this helper class:\nThe details of this method aren&#8217;t important.\nIn fact, for illustrative purposes, I&#8217;m going to skip\nthe call to <code>FormatMessage<\/code> and just return an ugly\nname.&sup2;\n<\/p>\n<pre>\nclass Trace {\n public static string GetLastErrorFriendlyName()\n {\n  return Marshal.GetLastWin32Error().ToString();\n }\n}\n<\/pre>\n<p>\nRun this program, and you should get this output:\n<\/p>\n<pre>\nError: 6\n<\/pre>\n<p>\nSix is the expected error code, since that is the numeric value of\n<code>ERROR_INVALID_HANDLE<\/code>.\n<\/p>\n<p>\nYou don&#8217;t think much of this program until one day you run it\nand instead of getting error 6, you get something like this:\n<\/p>\n<pre>\nError: 126\n<\/pre>\n<p>\nWhat happened?\n<\/p>\n<p>\nWhile you weren&#8217;t paying attention, somebody decided to do\nsome enhancements to the <code>Trace<\/code> class,\nmaybe added some new methods and stuff,\nand in particular, a static constructor got added:\n<\/p>\n<pre>\nclass Trace {\n public static string GetLastErrorFriendlyName()\n {\n  return Marshal.GetLastWin32Error().ToString();\n }\n <font COLOR=\"blue\">[DllImport(\"kernel32.dll\", SetLastError=true, CharSet=CharSet.Auto)]\n public static extern IntPtr LoadLibrary(string dll);\n static Trace() { LoadLibrary(\"enhanced_logging.dll\"); }<\/font>\n}\n<\/pre>\n<p>\nIt&#8217;s not important what the static constructor does;\nthe point is that we have a static constructor now.\nIn this case, the static constructor tries to load a helper DLL\nwhich presumably does something fancy so we can get better trace logging,\nsomething like that, the details aren&#8217;t important.\n<\/p>\n<p>\nThe important thing is that the constructor has a side effect.\nSince it uses a p\/invoke, the value of\n<code>Marshal.GetLastWin32Error()<\/code> is overwritten by the\nerror code returned by the <code>LoadLibrary<\/code>,\nwhich in our case is error&nbsp;126, <code>ERROR_MOD_NOT_FOUND<\/code>.\n<\/p>\n<p>\nNow let&#8217;s look at what happens in our program.\n<\/p>\n<p>\nFirst, we call <code>SetEvent<\/code>, which fails and sets the\nWin32 error code to&nbsp;6.\nNext, we call <code>Trace.GetLastErrorFriendlyName<\/code>,\nbut wait!\nThis is the first call to a method in the <code>Trace<\/code> class,\nso we have to run the static constructor first.\n<\/p>\n<p>\nThe static constructor tries to load the <code>enhanced_logging.dll<\/code>\nmodule, and it fails, setting the last error code to&nbsp;126.\nThis <i>overwrites the previous value<\/i>.\n<\/p>\n<p>\nAfter the static constructor returns, we return to our program already\nin progress and call <code>Trace.GetLastErrorFriendlyName<\/code>,\nbut it&#8217;s too late.\nThe damage has been done.\nThe last error code has been corrupted.\n<\/p>\n<p>\nAnd that&#8217;s why we get 126 instead of 6.\n<\/p>\n<p>\nWhat&#8217;s really scary is that problems with static constructors running\nat inopportune times are often extremely hard to identify.\nFor one thing, there is no explicit indication in the source code that\nthere&#8217;s any static constructor funny business going on.\nIndeed, somebody could just recompile the assembly containing the\n<code>Trace<\/code> class without modifying your program, and the problem\nwill rear its head.\n&#8220;But I didn&#8217;t change anything.\nThe timestamp on <code>program.exe<\/code> is the same as the one that\nstill works!&#8221;\n<\/p>\n<p>\nA side effect you might not consider is synchronization.\nIf the static constructor takes any locks,\nyou have to keep an eye on your lock hierarchy, or one of those\nlocks might trigger a deadlock.\nThis is insidious, because you can stare at the code all you want;\nyou won&#8217;t see anything.\nYou&#8217;ll have a method like\n<\/p>\n<pre>\nclass Trace {\n ...\n public static string GetFavoriteColor() { return \"blue\"; }\n}\n<\/pre>\n<p>\nand yet when you try to step over a call to\n<code>Trace.GetFavoriteColor<\/code>,\nyour program hangs!\n&#8220;This makes no sense.\nHow can <code>Trace.GetFavoriteColor<\/code> hang?\nIt just returns a constant!&#8221;\n<\/p>\n<p>\nAnother factor that makes this problem baffling is that\nthe problem occurs only the first time you call\na method in the <code>Trace<\/code> class.\nWe saw it here only because the very first thing we did with\n<code>Trace<\/code> was display an error.\nIf you happened to call, say,\n<code>Trace.GetFavoriteColor()<\/code> before calling\n<code>Trace.GetLastErrorFriendlyName()<\/code>,\nthen you wouldn&#8217;t have seen this problem.\nIn fact, that&#8217;s how the program that inspired today&#8217;s entry stumbled\nacross this problem.\nThey deleted a call into the <code>Trace<\/code> class from some unrelated\npart of the program,\nwhich meant that the static constructor\nran at a different time than it used to,\nand unfortunately, the new time was less hospitable to static construction.\n<\/p>\n<p>\n&#8220;I&#8217;m sorry, did I call you at a bad time?&#8221;\n<\/p>\n<p>\n<b>Footnotes<\/b>&sup3;\n<\/p>\n<p>\n&sup1;This is not strictly true.\nIn reality, it&#8217;s a bit of\nsleight-of-hand performed by the C runtime library.&#x2074;\n<\/p>\n<p>\n&sup2;For a less ugly name,\nyou can use this class instead:<\/p>\n<pre>\nclass Trace {\n [DllImport(\"kernel32.dll\", SetLastError=true)]\n public static extern IntPtr LocalFree(IntPtr hlocal);\n [DllImport(\"kernel32.dll\", SetLastError=true, CharSet=CharSet.Auto)]\n public static extern int FormatMessage(int flags, IntPtr unused1,\n    int error, int unused2, ref IntPtr result, int size, IntPtr unused3);\n static int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100;\n static int FORMAT_MESSAGE_IGNORE_INSERTS  = 0x00000200;\n static int FORMAT_MESSAGE_FROM_SYSTEM     = 0x00001000;\n public static string GetLastErrorFriendlyName()\n {\n  string result = null;\n  IntPtr str = IntPtr.Zero;\n  if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |\n                    FORMAT_MESSAGE_IGNORE_INSERTS  |\n                    FORMAT_MESSAGE_FROM_SYSTEM, IntPtr.Zero,\n                    Marshal.GetLastWin32Error(), 0,\n                    ref str, 0, IntPtr.Zero) &gt; 0) {\n   try {\n    result = Marshal.PtrToStringAuto(str);\n   } finally {\n    LocalFree(str);\n   }\n  }\n  return result;\n }\n}\n<\/pre>\n<p>\nNote that there may be better ways of accomplishing this.\nI&#8217;m not the expert here.\n<\/p>\n<p>\n&sup3;Boring footnote symbols from now on.\nYou guys sure know how to take the fun out of blogging.\n(I didn&#8217;t realize that blogs were held to academic writing standards.\nSilly me.)\nNow you can go spend your time telling\n<a HREF=\"http:\/\/scobleizer.com\/\">Scoble<\/a>\nthat he wrote a run-on sentence or something.\n<\/p>\n<p>\n&#x2074;Although this statement is written as if it were a fact,\nit is actually my interpretation of how the C runtime works\nand is\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2007\/08\/10\/4315707.aspx#4327521\">\nnot an official position<\/a>\nof the Visual Studio team\nnor Microsoft Corporation,\nand that interpretation may ultimately prove incorrect.\nSimilar remarks apply to other statements of fact in this article.\n<\/p>\n<p>\n<b>Postscript<\/b>:\nBefore you start pointing fingers and saying,\n&#8220;Hah hah, we don&#8217;t have this problem in Win32!&#8221;&mdash;it turns out that you do!\nAs we noted in the introduction,\nstatic constructors run when the DLL is loaded.\nThe granularity in Win32 is not as fine,\nbeing at the module level rather than the class level,\nbut the problem is still there.\nIf you use delay-loading,\nthen the first call to a function in a delay-loaded DLL\nwill load the target DLL, and its static constructors will run,\npossibly when your program wasn&#8217;t expecting it.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of the differences between C++ and C# is when static constructors run. In C++, static constructors are the first thing run in a module, even before the DllMain function runs.&sup1; In C#, however, static constructors don&#8217;t run until you use the class for the first time. If your static constructor has side effects, you [&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-25573","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>One of the differences between C++ and C# is when static constructors run. In C++, static constructors are the first thing run in a module, even before the DllMain function runs.&sup1; In C#, however, static constructors don&#8217;t run until you use the class for the first time. If your static constructor has side effects, you [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/25573","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=25573"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/25573\/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=25573"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=25573"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=25573"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}