提问人:MattTT 提问时间:6/15/2023 最后编辑:MattTT 更新时间:6/30/2023 访问量:160
VC++:使用 /MD 构建时:未解析的外部文件,如 _memset & _terminate & ___vcrt_initialize
VC++: when building with /MD: unresolved externals like _memset & _terminate & ___vcrt_initialize
问:
编辑:我终于能够解决所有未解析的符号 - 请参阅下面的答案。然而,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.lib
vcruntime.lib
使用我可以看到,既不
包含它也不
包含它。
但我可以在以下位置找到它:dumpbin /symbols "..." | find /i " _memset"
C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\ucrt\x86\ucrt.lib
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.32.31326\lib\x86\vcruntime.lib
libvcruntime.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
但这应该是静态的,所以不适合我,对吧?
任何提示如何获取缺少的功能??
答:
起初,您在我的问题中看到的是由一个旧对象产生的,该对象仍然是使用 /MT 编译的。更新此对象后,链接器输出中消失了。LIBCMT.lib
LIBCMT.lib
vcruntime.lib
确实包含像 .
并包含符号,如 、 和 。_memset, _memcpy
ucrt.lib
__imp__calloc
_terminate
_floor
库中包含的导出符号最终可以通过 查看。
( 没有显示例如 在 中。dumpbin /linkermember:1
dumpbin /exports
__imp__calloc
ucrt.lib
虽然链接器自动选择,但我必须手动指定 vcruntime.lib
和 ucrt.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.lib
msvcrt.lib
vcruntime.lib
msvcrt.lib
msvcrt.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。
最终链接良好。
因此,剩下要做的就是解释这种意外行为:
- 为什么链接器选择
_DllMainCRTStartup
作为默认入口点,但不符合其调用约定?
(请记住:当我简单地将(已经存在的)函数__DllMainCRTStartup@12
指定为入口点时,未解析的外部_DllMainCRTStartup
就会消失。 - 为什么链接器会错过这 11 个未解析的外部函数,而当我简单地将另一个函数 (
__DllMainCRTStartup@12
) 指定为入口点时,它们没有问题。 - 如果我确实使用自己的输入函数,这 11 个符号位于何处?
评论