{"id":111314,"date":"2025-06-26T07:00:00","date_gmt":"2025-06-26T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=111314"},"modified":"2025-06-26T09:20:51","modified_gmt":"2025-06-26T16:20:51","slug":"20250626-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20250626-00\/?p=111314","title":{"rendered":"Why do I get errors about some weird symbol called ?main@@YAHP$01E$AAV?$Array@PE$AAVString@Platform&#8230;, part 2"},"content":{"rendered":"<p>We are investigating <a title=\"Why do I get errors or warnings about some weird symbol called ?main@@YAHP$01E$AAV?$Array@PE$AAVString@Platform..., part 1\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20250625-00\/?p=111306\"> why a project is getting an error about a weird C++\/CX symbol<\/a>, and we thought we had figured it out, but our attempt to replicate the problem with a minimal example failed. So we must have removed something important from the example.<\/p>\n<p>Since the problem occurred when the project involved C++\/CX, let&#8217;s add C++\/CX to our minimal example. Maybe that will tell us something.<\/p>\n<pre style=\"white-space: pre-wrap;\">rem create a minimal fuzzer library\r\n&gt;lib.cpp echo void fuzzme(); int __cdecl main(int, char**) { fuzzme(); return 42; }\r\ncl \/c lib.cpp\r\nlib \/out:lib.lib lib.obj\r\n\r\nrem create our fuzzer plugin\r\n&gt;fuzzer.cpp echo void fuzzme() {}\r\ncl \/c fuzzer.cpp\r\n\r\n<span style=\"border: solid 1px currentcolor; border-bottom: none;\">rem new! Add a superfluous C++\/CX component<\/span>\r\n<span style=\"border: 1px currentcolor; border-style: none solid;\">&gt;cx.cpp echo ref class Dummy {};           <\/span>\r\n<span style=\"border: solid 1px currentcolor; border-top: none;\">cl \/c \/EHsc \/ZW cx.cpp                     <\/span>\r\n\r\nrem Try to link them all together\r\nlink \/out:fuzzer.exe \/subsystem:console fuzzer.obj <span style=\"border: solid 1px currentcolor;\">cx.obj<\/span> lib.lib\r\n<\/pre>\n<p>Output:<\/p>\n<pre style=\"white-space: pre-wrap;\">vccorlib.lib(climain.obj) : error LNK2019: unresolved external symbol \"?main@@YAHP$01E$AAV?$Array@<wbr \/>PE$AAVString@<wbr \/>Platform@@<wbr \/>$00@Platform@@@Z\" (?main@@YAHP$01E$AAV?$Array@<wbr \/>PE$AAVString@<wbr \/>Platform@@<wbr \/>$00@Platform@@@Z) referenced in function \"int __cdecl _main(void)\" (?_main@@YAHXZ)\r\n<\/pre>\n<p>Okay, <i>now<\/i> we get the error.<\/p>\n<p>So the presence of <code>cx.obj<\/code> introduces the problem.<\/p>\n<p>Let&#8217;s go back to the verbose log to see where <code>cx.obj<\/code> enters the picture.<\/p>\n<p>Actually, something interesting jumps out right at the start.<\/p>\n<pre style=\"white-space: pre-wrap;\">Starting pass 1\r\nProcessed \/DEFAULTLIB:LIBCMT\r\nProcessed \/DEFAULTLIB:OLDNAMES\r\n<span style=\"border: solid 1px currentcolor; border-bottom: none;\">Processed \/DEFAULTLIB:vccorlib.lib<\/span>\r\n<span style=\"border: solid 1px currentcolor; border-top: none;\">Processed \/DEFAULTLIB:MSVCRT      <\/span>\r\n<\/pre>\n<p>These two libraries got added as default libraries, and that&#8217;s how <code>vccorlib.lib<\/code> became one of the libraries participating in the module.<\/p>\n<p>If we dig into <code>cx.obj<\/code>, we can see where it requests those libraries.<\/p>\n<pre style=\"white-space: pre-wrap;\">link \/dump \/all cx.obj | findstr \/i defaultlib\r\n<\/pre>\n<p>Output:<\/p>\n<pre>   \/DEFAULTLIB:vccorlib.lib\r\n   \/DEFAULTLIB:MSVCRT\r\n   \/DEFAULTLIB:OLDNAMES\r\n<\/pre>\n<p>The compiler injects requests for three default libraries into <code>cx.obj<\/code>, so that&#8217;s how <code>vccorlib.lib<\/code> joins the set of default libraries.<\/p>\n<p>This explains why <code>cx.obj<\/code> is essential to the repro: It is <code>cx.obj<\/code> that pulls in <code>vccorlib.lib<\/code>, which means that a search for <code>main<\/code> finds the version in <code>vccorlib.lib<\/code> before it finds the one we want in <code>lib.lib<\/code>.<\/p>\n<p>Now that we understand the source of the problem, we&#8217;ll look at trying to fix it. Next time.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Figuring out why C++\/CX makes a difference.<\/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-111314","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Figuring out why C++\/CX makes a difference.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/111314","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=111314"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/111314\/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=111314"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=111314"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=111314"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}