VC++:使用 /MD 构建时:未解析的外部文件,如 _memset & _terminate & ___vcrt_initialize

VC++: when building with /MD: unresolved externals like _memset & _terminate & ___vcrt_initialize

提问人:MattTT 提问时间:6/15/2023 最后编辑:MattTT 更新时间:6/30/2023 访问量:160

问:

编辑:我终于能够解决所有未解析的符号 - 请参阅下面的答案。然而,MS 工具的行为仍然很神秘,不像记录的那样。

我有一个 ANT 项目,它使用 Win 10 上的 Visual Studio (C++) 2022 工具链进行构建。
所以没有 VS 项目 - 每个设置都是通过 ANT 完成的。

我想要一个 exe 和一个 dll 共享同一个 CRT。因此,我使用 /MD 编译器开关。

目前我在为dll而苦苦挣扎。
不幸的是,最后我得到了许多未解决的外部问题,即 、 、
和 ,它们被 LIBCMT 引用。LIB(这已经是一个提示了吗?
_floor_memset_memcpy_terminate

使用链接器开关,我分析了使用的库,如下所示:/VERBOSE:LIB

    Searching C:\Program Files (x86)\Windows Kits\10\\lib\10.0.19041.0\\um\x86\kernel32.lib:
    Searching C:\Program Files (x86)\Windows Kits\10\\lib\10.0.19041.0\\um\x86\rpcns4.lib:
    Searching C:\Program Files (x86)\Windows Kits\10\\lib\10.0.19041.0\\um\x86\rpcrt4.lib:
    Searching C:\Program Files (x86)\Windows Kits\10\\lib\10.0.19041.0\\um\x86\oleaut32.lib:
    Searching C:\Program Files (x86)\Windows Kits\10\\lib\10.0.19041.0\\um\x86\uuid.lib:
    Searching C:\Program Files (x86)\Windows Kits\10\\lib\10.0.19041.0\\um\x86\user32.lib:
    Searching C:\Program Files (x86)\Windows Kits\10\\lib\10.0.19041.0\\um\x86\gdi32.lib:
    Searching C:\Program Files (x86)\Windows Kits\10\\lib\10.0.19041.0\\um\x86\winspool.lib:
    Searching C:\Program Files (x86)\Windows Kits\10\\lib\10.0.19041.0\\um\x86\comdlg32.lib:
    Searching C:\Program Files (x86)\Windows Kits\10\\lib\10.0.19041.0\\um\x86\advapi32.lib:
    Searching C:\Program Files (x86)\Windows Kits\10\\lib\10.0.19041.0\\um\x86\shell32.lib:
    Searching C:\Program Files (x86)\Windows Kits\10\\lib\10.0.19041.0\\um\x86\ole32.lib:
    Searching C:\Program Files (x86)\Windows Kits\10\\lib\10.0.19041.0\\um\x86\odbc32.lib:
    Searching C:\Program Files (x86)\Windows Kits\10\\lib\10.0.19041.0\\um\x86\odbccp32.lib:
    Searching C:\Program Files (x86)\Windows Kits\10\\lib\10.0.19041.0\\um\x86\Ws2_32.lib:
    Searching C:\Program Files (x86)\Windows Kits\10\\lib\10.0.19041.0\\um\x86\Psapi.lib:
    Searching C:\Program Files (x86)\Windows Kits\10\\lib\10.0.19041.0\\um\x86\IPHlpApi.Lib:
    Searching C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.32.31326\lib\x86\delayimp.lib:
    Searching C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.32.31326\lib\x86\LIBCMT.lib:
    Searching C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.32.31326\lib\x86\OLDNAMES.lib:
    Searching C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.32.31326\lib\x86\msvcprt.lib:
    Searching C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.32.31326\lib\x86\MSVCRT.lib:

msvcrt.lib根据这个 MS 文档,似乎是合适的。它显然是由链接器自动选择的。
但是,我不明白在什么情况下应该选择其他提到的库:和.
ucrt.libvcruntime.lib

使用我可以看到,既不
包含它也不
包含它。
但我可以在以下位置找到它:
dumpbin /symbols "..." | find /i " _memset"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\ucrt\x86\ucrt.libC:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.32.31326\lib\x86\vcruntime.liblibvcruntime.lib

> dumpbin /symbols "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.32.31326\lib\x86\libvcruntime.lib"  | find /i " _memset"
011 00000000 SECT6  notype ()    External     | _memset

但这应该是静态的,所以不适合我,对吧?

任何提示如何获取缺少的功能??

Visual-C++ 链接器 链接器错误 未解决的外部 CRT

评论


答:

0赞 MattTT 6/15/2023 #1

起初,您在我的问题中看到的是由一个旧对象产生的,该对象仍然是使用 /MT 编译的。更新此对象后,链接器输出中消失了。LIBCMT.libLIBCMT.lib


vcruntime.lib确实包含像 .
并包含符号,如 、 和 。
_memset, _memcpyucrt.lib__imp__calloc_terminate_floor

库中包含的导出符号最终可以通过 查看。
( 没有显示例如 在 中。
dumpbin /linkermember:1dumpbin /exports__imp__callocucrt.lib

虽然链接器自动选择,但我必须手动指定 vcruntime.libucrt.lib。(有谁知道为什么?msvcrt.lib)


在那之后,我留下了以下 11 个未解析的符号:

msvcrt.lib(utility.obj) : error LNK2019: unresolved external symbol ___vcrt_initialize referenced in function ___scrt_initialize_crt
msvcrt.lib(utility.obj) : error LNK2019: unresolved external symbol ___vcrt_uninitialize referenced in function ___scrt_initialize_crt
msvcrt.lib(utility.obj) : error LNK2019: unresolved external symbol ___vcrt_uninitialize_critical referenced in function ___scrt_dllmain_uninitialize_critical
msvcrt.lib(utility.obj) : error LNK2019: unresolved external symbol ___vcrt_thread_attach referenced in function ___scrt_dllmain_crt_thread_attach
msvcrt.lib(utility.obj) : error LNK2019: unresolved external symbol ___vcrt_thread_detach referenced in function ___scrt_dllmain_crt_thread_attach
msvcrt.lib(utility.obj) : error LNK2019: unresolved external symbol __is_c_termination_complete referenced in function ___scrt_dllmain_uninitialize_c
msvcrt.lib(utility.obj) : error LNK2019: unresolved external symbol ___acrt_initialize referenced in function ___scrt_initialize_crt
msvcrt.lib(utility.obj) : error LNK2019: unresolved external symbol ___acrt_uninitialize referenced in function ___scrt_uninitialize_crt
msvcrt.lib(utility.obj) : error LNK2019: unresolved external symbol ___acrt_uninitialize_critical referenced in function ___scrt_dllmain_uninitialize_critical
msvcrt.lib(utility.obj) : error LNK2019: unresolved external symbol ___acrt_thread_attach referenced in function ___scrt_dllmain_crt_thread_attach
msvcrt.lib(utility.obj) : error LNK2019: unresolved external symbol ___acrt_thread_detach referenced in function ___scrt_dllmain_crt_thread_detach

这似乎与这个 SO 问题中的问题相同。它没有真正好的答案(目前),但那里的评论指的是这个 MS 社区问题。解决方案是删除 /ENTRY:myEntryPoint


在此之后,我最终得到了未解决的外部_DllMainCRTStartup

我无法按照 MS 文档所述找到此符号,但是我在 中找到__DllMainCRTStartup@12
已经使用过;并且也已经使用过。症结在于:
包含函数的变体——我需要的是变体。
vcruntime.libmsvcrt.libvcruntime.libmsvcrt.libmsvcrt.lib__stdcall__cdecl

所以我决定建造一座这样的小

extern "C" BOOL __stdcall _DllMainCRTStartup(
    HINSTANCE hinstDLL, 
    DWORD fdwReason,    
    LPVOID lpvReserved );

extern "C" BOOL __cdecl DllMainCRTStartup(
    HINSTANCE hinstDLL,  // handle to DLL module
    DWORD fdwReason,     // reason for calling function
    LPVOID lpvReserved )  // reserved
{
      return _DllMainCRTStartup( hinstDLL,  
                                 fdwReason,     
                                 lpvReserved ); 
}

这链接没有错误,但是我收到了警告

warning LNK4086: entrypoint '_DllMainCRTStartup' is not __stdcall with 12 bytes of arguments; image may not run

这使我找到了将函数指定为入口点的解决方案:msvcrt.lib

/ENTRY:__DllMainCRTStartup@12

我删除了我的桥并制作了一个普通的 DllMain


最终链接良好。


因此,剩下要做的就是解释这种意外行为:

  1. 为什么链接器选择 _DllMainCRTStartup 作为默认入口点,但不符合其调用约定?
    (请记住:当我简单地将(已经存在的)函数__DllMainCRTStartup@12指定为入口点时,未解析的外部_DllMainCRTStartup就会消失。
  2. 为什么链接器会错过这 11 个未解析的外部函数,而当我简单地将另一个函数 (__DllMainCRTStartup@12) 指定为入口点时,它们没有问题。
  3. 如果我确实使用自己的输入函数,这 11 个符号位于何处