{"id":11173,"date":"2011-03-21T07:00:00","date_gmt":"2011-03-21T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2011\/03\/21\/how-does-the-c-runtime-know-whether-to-use-the-static-linking-or-dynamic-linking-version-of-the-header-file\/"},"modified":"2011-03-21T07:00:00","modified_gmt":"2011-03-21T07:00:00","slug":"how-does-the-c-runtime-know-whether-to-use-the-static-linking-or-dynamic-linking-version-of-the-header-file","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20110321-00\/?p=11173","title":{"rendered":"How does the C runtime know whether to use the static-linking or dynamic-linking version of the header file?"},"content":{"rendered":"<p>\nIn response to a description of what happens when you get\n<code>dll&shy;import<\/code> wrong,\nnksingh asks,\n&#8220;This seems like a problem for the CRT.\nAs far as I know,\nVC gives you the option of statically or dynamically linking the CRT.\nBut it seems like the headers will have to make a choice to support\none thing better than the other.\nConditional compilation would work,\nbut then people would have to remember to include a #define somewhere.\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2006\/07\/26\/679044.aspx#679103\">\nIs this dllimport vs. static linking thing something the compiler could figure out on its own if you&#8217;re doing Link-time codegen<\/a>?&#8221;\n<\/p>\n<p>\nLet&#8217;s start from the beginning.\n<\/p>\n<p>\nYes, this would be a problem for the CRT since it wouldn&#8217;t know whether\nto declare the functions as normal static functions or as\n<code>dllimport<\/code>-style functions,\nand the headers have to make a choice which way to go.\n<\/p>\n<p>\nAnd if you look at the headers, you can see that it is indeed done\nvia conditional compilation.\n<\/p>\n<pre>\n...\n_CRTIMP int __cdecl fflush(FILE * _File);\n...\n<\/pre>\n<p>\nThis magic <code>_CRTIMP<\/code> symbol is defined in\n<code>crtdefs.h<\/code> like so:\n<\/p>\n<pre>\n\/* Define _CRTIMP *\/\n#ifndef _CRTIMP\n#ifdef _DLL\n#define _CRTIMP __declspec(dllimport)\n#else  \/* _DLL *\/\n#define _CRTIMP\n#endif  \/* _DLL *\/\n#endif  \/* _CRTIMP *\/\n<\/pre>\n<p>\nConditional compilation decides whether <code>_CRTIMP<\/code>\nexpands to <code>__declspec(dllimport)<\/code> or to nothing at all,\ndepending on whether the <code>_DLL<\/code> symbol is defined.\n<\/p>\n<p>\nAnd yet nobody bothers writing <code>#define _DLL<\/code> before\nthey <code>#include &lt;stdio.h&gt;<\/code>.\nThere must be something else going on.\n<\/p>\n<p>\nIn fact, we can run some experiments to see what&#8217;s going on.\n<\/p>\n<pre>\n#ifdef _DLL\n#error \"_DLL is defined\"\n#else\n#error \"_DLL is not defined\"\n#endif\n<\/pre>\n<p>\nSave this as <code>dummy.c<\/code> and run a few tests.\n<\/p>\n<pre>\nC:\\tests&gt; cl \/MT dummy.c\ndummy.c\ndummy.c(4) : fatal error C1189: #error :  \"_DLL is not defined\"\nC:\\tests&gt; cl \/MD dummy.c\ndummy.c\ndummy.c(2) : fatal error C1189: #error :  \"_DLL is defined\"\n<\/pre>\n<p>\nWell how&#8217;s about that.\nThe compiler uses the <code>\/MT<\/code> and <code>\/MD<\/code>\nflag to decide whether or not to define the preprocessor symbol\n<code>_DLL<\/code>, which is the secret signal it passes to the\n<code>crtdef.h<\/code> header file to control the conditional\ncompilation.\n<\/p>\n<p>\nThe compiler has to use this technique\ninstead of deferring the decision to link-time code generation\nbecause it cannot assume that everybody has enabled link-time\ncode generation.\n(Indeed, we explicitly did not in our sample command lines.)\n<\/p>\n<p>\nIf link-time code generation were enabled, then is this something\nthat could be deferred until that point?\n<\/p>\n<p>\nIn principle yes,\nbecause link-time code generation in theory could just make the .obj\nfile a copy of the source file (and all the header files) and do\nall the actual compiling at link time.\nThis is a sort of extreme way of doing it,\nbut I guess it could&#8217;ve been done that way.\n<\/p>\n<p>\nOn the other hand, it also means that the compiler folks would have\nto come up with a new nonstandard extension that means &#8220;This function\nmight be a normal static function or it might be a\n<code>dll&shy;import<\/code>\nfunction. I haven&#8217;t decided yet; I&#8217;ll tell you later.&#8221;\n<\/p>\n<p>\nSeeing as how the CRT already has to solve the problem in the case\nwhere there is no link-time code generation, it doesn&#8217;t seem worth\nthe effort to add a feature to link-time-code generation\nthat you don&#8217;t actually need.\nIt would be a feature for which the only client is the C runtime\nlibrary itself, for which the C runtime library already requires\na separate solution when link-time code generation is disabled,\nand for which that separate solution <i>still works when link-time\ncode generation is enabled<\/i>.\n<\/p>\n<p>\nNo engineering purpose is served by\nwriting code just for the sake of writing code.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In response to a description of what happens when you get dll&shy;import wrong, nksingh asks, &#8220;This seems like a problem for the CRT. As far as I know, VC gives you the option of statically or dynamically linking the CRT. But it seems like the headers will have to make a choice to support one [&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":[26],"class_list":["post-11173","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-other"],"acf":[],"blog_post_summary":"<p>In response to a description of what happens when you get dll&shy;import wrong, nksingh asks, &#8220;This seems like a problem for the CRT. As far as I know, VC gives you the option of statically or dynamically linking the CRT. But it seems like the headers will have to make a choice to support one [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/11173","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=11173"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/11173\/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=11173"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=11173"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=11173"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}