链接问题(VC6)
我打开了一个旧的工作区,它是一个库及其测试工具。 它曾经工作得很好,但现在不行了,旧版本的代码也无法工作,并出现相同的错误。 我尝试重新创建该项目,这也会导致相同的错误。 项目设置中似乎没有任何问题,并且生成的代码可以在主应用程序中运行。
我已经删除了大部分文件并将其减少到生成错误的最低限度。 不幸的是,我无法发布该项目,因为这是在生产代码中使用的。
我收到的 LNK2001 链接器错误通常意味着我放弃了库或忘记实现虚拟函数。 然而,这是标准模板库的一部分 - 并且是其中的标头。
IOCompletionPort.obj 中列出的存在问题的代码实际上并不直接使用 std::string
,而是调用了一个执行以下操作的类:Comms::Exception
接受 std::string
和 GetLastError
或 WSAGetLastError
的值。
错误中提到的函数 (GetMessage
) 已实现,但它是一个虚函数,因此其他类可以根据需要重写它。 然而,编译器似乎已将其作为 ANSI 版本,但我在设置中找不到任何可以控制它的选项。 我怀疑这可能是问题所在,但由于图书馆的选项很少,我无法确定。 但是,这两个项目都在编译器选项中指定了 _MBCS。
--------------------配置:TestComms - Win32 调试--------------------链接... Comms.lib(IOCompletionPort.obj) :错误LNK2001:无法解析的外部符号“public:虚拟类 std::basic_string
__thiscall Comms::Exception::GetMessageA(void)const " (?GetMessageA@ 异常@Comms@@UBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ) 调试/TestComms.exe:致命错误 LNK1120:1 个未解析的外部 执行 link.exe 时出错。 TestComms.exe - 2 个错误,0 个警告
有什么建议吗? 我已经为此浪费了上午的大部分时间,并且不想也浪费下午的大部分时间。
I've opened an old workspace that is a library and its test harness. It used to work fine but now doesn't and older versions of the code don't work either with the same errors. I've tried recreating the project and that causes the same errors too. Nothing seems out of order in project settings and the code generated works in the main app.
I've stripped out most of the files and got it down to the bare minimum to generate the error. Unfortunately, I can't post the project as this is used in production code.
The LNK2001 linker error I get usually means I've left off a library or forgot to implement a virtual function. However, this is part of the standard template library - and is a header at that.
The code that is listed as having the problem in IOCompletionPort.obj doesn't actually use std::string
directly, but does call a class that does: Comms::Exception
accepts a std::string
and the value of GetLastError
or WSAGetLastError
.
The function mentioned in the error (GetMessage
) is implemented but is a virtual function so other classes can override it if need be. However it appears that the compiler has made it as an ANSI version, but I can't find any options in the settings that would control that. I suspect that might be the problem but since there's very little in the way of options for the library I have no way of knowing for sure. However, both projects specify _MBCS in the compiler options.
--------------------Configuration: TestComms - Win32 Debug-------------------- Linking... Comms.lib(IOCompletionPort.obj)
: error LNK2001: unresolved external symbol "public: virtual class
std::basic_string<char,struct std::char_traits,class
std::allocator > __thiscall
Comms::Exception::GetMessageA(void)const " (?GetMessageA@
Exception@Comms@@UBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ)
Debug/TestComms.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.TestComms.exe - 2 error(s), 0 warning(s)
Any suggestions? I've lost most of the morning to this and don't want to lose most of the afternoon too.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
一种可能性在于 Win32 ANSI/Unicode“名称修改”,它将符号
GetMessage
转换为GetMessageA
或GetMessageW
。 有三种可能:Windows.h 尚未加载,因此
GetMessage
保持GetMessage
Windows.h 加载了 ANSI 的符号集,因此
GetMessage
变为GetMessageA
Windows.h 加载了 Unicode 的符号集,因此
GetMessage
变为GetMessageW
如果您已如果以触发两种不同场景的方式编译两个不同的文件,您将收到链接器错误。 错误消息表明
Comms::Exception
类是上面#2 的实例——也许它在 windows.h 尚未加载的地方使用?我会代替你做其他事情,就像例行公事一样:
1)确保我的包含路径和库路径不包含任何我不期望的内容。
2) 执行“构建清理”,然后手动验证它,如有必要,删除任何额外的目标文件。
3) 确保 include 语句中不存在任何与项目最初重建时的含义不同的硬编码路径。
编辑:与格式作斗争:(
One possibility lies with Win32 ANSI/Unicode "name-mangling", which turns the symbol
GetMessage
into eitherGetMessageA
orGetMessageW
. There are three possibilities:Windows.h hasn't been loaded, so
GetMessage
staysGetMessage
Windows.h was loaded with symbols set for ANSI, so
GetMessage
becomesGetMessageA
Windows.h was loaded with symbols set for Unicode, so
GetMessage
becomesGetMessageW
If you've compiled two different files in ways that trigger two different scenarios, you'll get a linker error. The error message indicates that the
Comms::Exception
class was an instance of #2, above -- perhaps it's used somewhere that windows.h hasn't been loaded?Other things I'd do in your place, just as a matter of routine:
1) Ensure that my include and library paths don't contain anything that I'm not expecting.
2) Do a "build clean" and then manually verify it, deleting any extra object files if necessary.
3) Make sure there aren't any hardcoded paths in include statements that don't mean what they meant when the project was originally rebuilt.
EDIT: Fighting with the formatting :(
@Curt:我认为你是最接近的。 我还没有测试过这个,但我想我在最初的问题中给出了答案。
GetMessage 是 Windows.h 中的一个定义,包含在 ifndef 块中在 Ansi (GetMessageA) 和 Unicode (GetMessageW) 之间切换。
@Curt: I think you came the closest. I haven't tested this but I think I sort of gave the answer in my original question.
GetMessage is a define in Windows.h wrapped in a ifndef block to switch between Ansi (GetMessageA) and Unicode (GetMessageW).
这是 Microsoft 处理 ANSI 与 Unicode API 方式的普遍问题。 由于它们全部(或几乎全部)都是通过为解析为函数名称的“A”或“W”版本的函数名称定义宏来完成的,因此您不能在命名空间/类/结构/枚举/中安全地拥有标识符与 Windows API 名称匹配的函数。
windows.h 宏对所有其他命名空间都粗暴地运行。
This is a general problem with the way Microsoft handled the ANSI vs. Unicode APIs. Since they are all (or pretty much all) done by defining macros for the function names that resolve to the 'A' or 'W' versions of the function names you cannot safely have an identifier in your namespace/class/struct/enum/function that matches a Windows API name.
The windows.h macros run roughshod over all other namespaces.
假设您没有在项目设置中删除一些您不应该拥有的东西(这是我期望像 User32.lib 这样的外部依赖项的地方):
检查工具| 选项| 目录 | 库(这里凭记忆)并确保您没有错过 common-all-garden 品种 lib 目录(同样,如果我面前没有 VC6,我无法告诉您它们是什么)
Presuming you haven't futzed around with the Project settings deleting something you ought not have (which is where I'd expect external dependencies like User32.lib to be):
Check Tools | Options | Directories | Libraries (going from memory here) and ensure that you're not missing the common-all-garden variety lib directories (again, without VC6 in front of me, I can't tell you what they are)
windows.h 在 IOCompletionPort.h 的顶部声明为包含 - 我厌倦了看到 7 行只是包含 1 个文件,因此我将其包装为自己的文件并包含它本身。 这还包含一些额外的#defines(即 ULONG_PTR),因为我们的主应用程序不会在安装了 Platform SDK 的情况下进行编译:-(
windows.h is declared at the top of IOCompletionPort.h as an include - I was sick of seeing 7 lines just to include 1 file so I have wrapped it its own file and includes that itself. This also contains some additional #defines (i.e. ULONG_PTR) as our main app won't compile with the Platform SDK installed:-(