{"id":5593,"date":"2013-01-10T07:00:00","date_gmt":"2013-01-10T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2013\/01\/10\/understanding-the-classical-model-for-linking-sometimes-you-dont-want-a-symbol-to-come-along-for-a-ride\/"},"modified":"2013-01-10T07:00:00","modified_gmt":"2013-01-10T07:00:00","slug":"understanding-the-classical-model-for-linking-sometimes-you-dont-want-a-symbol-to-come-along-for-a-ride","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20130110-00\/?p=5593","title":{"rendered":"Understanding the classical model for linking: Sometimes you don&#8217;t want a symbol to come along for a ride"},"content":{"rendered":"<p>Continuing our study of\n<A HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2013\/01\/07\/10382714.aspx\">\nthe classical model for linking<\/A>,\nlet&#8217;s take another look at the trick of\n<A HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2013\/01\/08\/10383017.aspx\">\ntaking symbols along for the ride<\/A>.\n<\/P>\n<P>\nThe technique of taking symbols along for the ride is quite handy\nif that&#8217;s what you want,\nbut sometimes you don&#8217;t actually want it.\nFor example, a symbol taken along for the ride may create\nconflicts or create unwanted dependencies.\n<\/P>\n<P>\nHere&#8217;s an example:\nSuppose you have a library called <CODE>stuff.lib<\/CODE>\nwhere you put functions that are\nused by various modules in different projects.\nOne of the files in your library might look like this:\n<\/P>\n<PRE>\n\/\/ filedatestuff.cpp<\/p>\n<p>BOOL GetFileCreationTimeW(\n        LPCWSTR pszFile,\n        FILETIME *pft)\n{\n    WIN32_FILE_ATTRIBUTE_DATA wfad;\n    BOOL fSuccess = GetFileAttributesExW(pszFile,\n                             GetFileExInfoStandard,\n                             &amp;wfad);\n    if (fSuccess) {\n        *pft = wfad.ftCreationTime;\n    } else {\n        pft-&gt;dwLowDateTime = 0;\n        pft-&gt;dwHighDateTime = 0;\n    }\n    return fSuccess;\n}<\/p>\n<p>BOOL GetFileCreationTimeAsStringW(\n         LPCWSTR pszFile,\n         LPWSTR pszBuf,\n         UINT cchBuf)\n{\n    FILETIME ft;\n    BOOL fSuccess = GetFileCreationTimeW(pszFile, &amp;ft);\n    if (fSuccess) {\n        fSuccess = SHFormatDateTimeW(&amp;ft, NULL,\n                                     pszBuf, cchBuf) &gt; 0;\n    }\n    return fSuccess;\n}\n<\/PRE>\n<P>\nThings are working out great,\npeople like the helper functions in your library,\nand then you get a bug report:\n<\/P>\n<BLOCKQUOTE CLASS=\"q\">\nWhen my program calls the\n<CODE>Get&shy;File&shy;Creation&shy;TimeW<\/CODE>\nfunction,\nI get a linker error:\n<TT>unresolved external: __imp__SHFormat&shy;Date&shy;TimeW<\/TT>.\nIf I remove my call to \n<CODE>Get&shy;File&shy;Creation&shy;TimeW<\/CODE>,\nthen my program builds fine.\n<\/BLOCKQUOTE>\n<P>\nYou scratch your head.\n&#8220;The program is calling\n<CODE>Get&shy;File&shy;Creation&shy;TimeW<\/CODE>,\nbut that function doesn&#8217;t call\n<CODE>SHFormat&shy;Date&shy;TimeW<\/CODE>,\nso why are we getting an unresolved external error?\nAny why hasn&#8217;t anybody else run into this problem before?&#8221;\n<\/P>\n<P>\nFirst question first.\nWhy are we getting an unresolved external error\nfor a nonexistent external dependency?\n<\/P>\n<P>\nBecause the\n<CODE>Get&shy;File&shy;Creation&shy;Time&shy;As&shy;StringW<\/CODE>\nfunction got <I>taken along for the ride<\/I>.\nWhen the customer&#8217;s program called\n<CODE>Get&shy;File&shy;Creation&shy;TimeW<\/CODE>,\nthat pulled in the <CODE>filedatestuff.obj<\/CODE> file,\nand that OBJ file contains both\n<CODE>Get&shy;File&shy;Creation&shy;TimeW<\/CODE>\n<I>and<\/I>\n<CODE>Get&shy;File&shy;Creation&shy;Time&shy;As&shy;StringW<\/CODE>.\nSince they are in the same OBJ file,\npulling in one function pulls in all of them.\n<\/P>\n<P>\nThe fix is to split the <CODE>filedatastuff.cpp<\/CODE> file\ninto two files,\none for each function.\nThat way, when you pull in one function,\nnobody else comes along for the ride.\n<\/P>\n<P>\nNow to the second half of the question:\nWhy did nobody run into this problem before?\n<\/P>\n<P>\nThe\n<CODE>Get&shy;File&shy;Creation&shy;TimeW<\/CODE>\nfunction has a dependency on\n<CODE>Get&shy;File&shy;Attributes&shy;ExW<\/CODE>,\nwhich is a function in <CODE>KERNEL32.DLL<\/CODE>.\nOn the other hand, the\n<CODE>Get&shy;File&shy;Creation&shy;Time&shy;As&shy;StringW<\/CODE>\nfunction has a dependency on\n<CODE>SHFormat&shy;Date&shy;TimeW<\/CODE>,\nwhich is a function in\n<CODE>SHLWAPI.DLL<\/CODE>.\nIf somebody lists\n<CODE>KERNEL32.LIB<\/CODE> as a dependent library\nin their project,\nbut they don&#8217;t include\n<CODE>SHLWAPI.LIB<\/CODE> on that list,\nthen they will encounter this problem\nbecause the linker will pull in the reference to\n<CODE>SHFormat&shy;Date&shy;TimeW<\/CODE>\nand have no way of resolving it.\n<\/P>\n<P>\nNobody ran into this before because <CODE>SHLWAPI.LIB<\/CODE>\nhas lots of cute little functions in it,\nso most people include it in their project.\nOnly if somebody is being frugal and leaving\n<CODE>SHLWAPI.LIB<\/CODE> out of their project\nwill they run into this problem.\n<\/P>\n<P>\n<B>Bonus chatter<\/B>:\nThe suggestion to split the file into two will work,\nbut if you are really clever, you can still do some consolidation.\nInstead of splitting up files by functional group\n(for example, &#8220;all <CODE>FILETIME<\/CODE> functions&#8221;),\nyou need to split them up based on their dependencies\n(&#8220;functions that are dependent solely on <CODE>SHLWAPI.LIB<\/CODE>&#8220;).\nOf course, this type of organization may make the code harder\nto follow (&#8220;Why did you put\n<CODE>Get&shy;File&shy;Creation&shy;Time&shy;As&shy;StringW<\/CODE>\nand\n<CODE>Hash&shy;String<\/CODE>\nin the same file?&#8221;),\nso you have to balance this against maintainability and\nreadability.\nFor example, somebody who is not aware of the classical\nmodel for linking may add a function to the file that has\na dependency on <CODE>SHELL32.DLL<\/CODE>,\nand now your careful separation has fallen apart.\n<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Continuing our study of the classical model for linking, let&#8217;s take another look at the trick of taking symbols along for the ride. The technique of taking symbols along for the ride is quite handy if that&#8217;s what you want, but sometimes you don&#8217;t actually want it. For example, a symbol taken along for the [&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,131],"class_list":["post-5593","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code","tag-linker"],"acf":[],"blog_post_summary":"<p>Continuing our study of the classical model for linking, let&#8217;s take another look at the trick of taking symbols along for the ride. The technique of taking symbols along for the ride is quite handy if that&#8217;s what you want, but sometimes you don&#8217;t actually want it. For example, a symbol taken along for the [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/5593","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=5593"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/5593\/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=5593"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=5593"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=5593"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}