1

我正在针对一些遗留的第三方库构建一个应用程序,并且在链接阶段遇到问题。我正在尝试使用 Visual Studio 9 进行编译。我的编译命令是:

cl -DNT40 -DPOMDLL -DCRTAPI1=_cdecl
-DCRTAPI2=cdecl -D_WIN32 -DWIN32 -DWIN32_LEAN_AND_MEAN -DWNT -DBYPASS_FLEX -D_INTEL=1 -DIPLIB=none -I. -I"D:\src\include" -I"C:\Program Files\Microsoft Visual Studio
9.0\VC\include" -c -nologo -EHsc -W1 -Ox -Oy- -MD mymain.c

代码编译干净。链接命令是:

link -debug -nologo -machine:IX86
-verbose:lib -subsystem:console mymain.obj wsock32.lib advapi32.lib
msvcrt.lib oldnames.lib kernel32.lib
winmm.lib [snip large list of
dependencies] D:\src\lib\app_main.obj
-out:mymain.exe

我得到的错误是:

app_main.obj : error LNK2019:
unresolved external symbol
"_\_declspec(dllimport) public: void
__thiscall std::locale::facet::_Register(void)"
(__imp_?_Register@facet@locale@std@@QAEXXZ)
referenced in function "class
std::ctype<char> const & __cdecl
std::use_facet<class std::ctype<char>
(class std::locale const &)" (??$use_facet@V?$ctype@D@std@@@std@@YAABV?$ctype@D@0@ABVlocale@0@@Z)

app_main.obj : error LNK2019:
unresolved external symbol
"__declspec(dllimport)  public: static
unsigned int __cdecl
std::ctype<char>::_Getcat(class
std::locale::facet const * *)"
(__imp_?_Getcat@?$ctype@D@std@@SAIPAPBVfacet@locale@2@@Z)
referenced in function "class
std::ctype<char> const & __cdecl
std::use_facet<class std::ctype<char>
(class std::locale const &)" (??$use_facet@V?$ctype@D@std@@@std@@YAABV?$ctype@D@0@ABVlocale@0@@Z)

app_main.obj : error LNK2019:
unresolved external symbol
"__declspec(dllimport)  public: static
unsigned int __cdecl
std::ctype<unsigned
short>::_Getcat(class
std::locale::facet const * *)"
(__imp_?_Getcat@?$ctype@G@std@@SAIPAPBVfacet@locale@2@@Z)
referenced in function "class
std::ctype<unsigned short> const &
__cdecl std::use_facet<class std::ctype<unsigned short> >(class
std::locale const &)"
(??$use_facet@V?$ctype@G@std@@@std@@YAABV?$ctype@G@0@ABVlocale@0@@Z)

mymain.exe : fatal error LNK1120: 3
unresolved externals

请注意,这些错误来自遗留代码,而不是我的代码 - app_main.obj 是遗留代码的一部分,而 mymain.c 是我的源代码。我做了一些搜索,我读到的内容表明这种类型的错误是由我的代码和我链接到的库之间的 -MD 开关不匹配引起的。由于我正在处理遗留代码,因此解决方案必须来自我的环境。自从我完成 C++ 工作以来已经有很长时间了,而且自从我使用 Visual Studio 以来已经有很长时间了,所以我希望这只是我的一些无知。关于如何解决这些问题的任何想法?

4

4 回答 4

4

这些是标准库参考。确保所有库(包括标准库)都使用相同的链接。例如,您不能在动态链接标准库时进行静态链接。使用的线程模型也是如此。请特别注意您和第 3 方库使用相同的链接选项。

这对 *ss 来说可能是一个真正的痛苦。

于 2008-08-22T19:06:53.623 回答
2

MSDN上检查:

  • /MD 使您的应用程序使用运行时库的多线程和 DLL 特定版本。
  • /MT 使您的应用程序使用运行时库的多线程静态版本。

注意:“...这样链接器将使用 LIBCMT.lib 来解析外部符号”

所以你需要一组不同的库。

我如何找出要链接的库:

  1. 找到一个可以链接的配置,添加 /verbose 选项。
  2. 将输出通过管道传输到文本文件。
  3. 尝试链接的配置。
  4. 在步骤 2 的详细输出中查找未解析的符号(在您的情况下为“_declspec(dllimport) public: void thiscall std::locale::facet::Register(void)”)并找到使用的库。
  5. 将这些库添加到您要链接的库列表中。

老学校,但它对有用。

于 2008-08-25T15:18:38.140 回答
2

如果您仍然希望使用 VS2008(或将来)编译项目,我可以建议使用二进制编辑器来查看有问题的目标文件mainapp.obj

这是我的一个小项目的一个例子。

zdbException.obj 包含以下摘录

DEFAULTLIB:"libc
pmtd" /DEFAULTLI
B:"uuid.lib" /DE
FAULTLIB:"uuid.l
ib" /include:?id
@?$num_put@DV?$o
streambuf_iterat
or@DU?$char_trai
ts@D@std@@@std@@
@std@@2V0locale@
2@A /include:?id
@?$numpunct@D@st
d@@2V0locale@2@A
 /DEFAULTLIB:"LI
BCMTD" /DEFAULTL
IB:"OLDNAMES" /E
DITANDCONTINUE 

注意条目/DEFAULTLIB:"LIBCMTD"。这表明目标文件是使用静态 c 运行时多线程调试编译的。

obj 中引用的函数也有可能在 VS2008 附带的标准运行时库中被弃用。

于 2008-09-04T22:07:21.743 回答
-2

在尝试让这些东西在 VS 2008 下编译后,我尝试了早期版本的 VS - 2005 使用警告,而 2003 刚刚工作。我仔细检查了链接,找不到任何问题,所以要么我找不到它,要么这不是问题。

所以重申一下,降级到 VS 2003 修复了它。

于 2008-08-25T15:02:24.777 回答