题
我打开了一个旧的工作区,它是一个库及其测试工具。它曾经工作得很好,但现在不行了,旧版本的代码也无法工作,并出现相同的错误。我尝试重新创建该项目,这也会导致相同的错误。项目设置中似乎没有任何问题,并且生成的代码可以在主应用程序中运行。
我已经删除了大部分文件并将其减少到生成错误的最低限度。不幸的是,我无法发布该项目,因为这是在生产代码中使用的。
我收到的 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,class std ::分配器> __ thiscall comms ::异常@@ v?$ selcator@d@2 @@ std @@ xz)debug/testcomms.exe:致命错误 LNK1120:1未解决的外部错误执行link.exe。
TestComms.exe - 2 个错误,0 个警告
有什么建议么?我已经为此浪费了上午的大部分时间,并且不想也浪费下午的大部分时间。
解决方案
一种可能性在于 Win32 ANSI/Unicode“名称修改”,它将符号 GetMessage
进入任一 GetMessageA
或者 GetMessageW
. 。有以下三种可能:
Windows.h 尚未加载,因此
GetMessage
停留GetMessage
Windows.h 加载了 ANSI 符号集,因此
GetMessage
变成GetMessageA
Windows.h 加载了 Unicode 符号集,因此
GetMessage
变成GetMessageW
如果您以触发两种不同场景的方式编译了两个不同的文件,您将收到链接器错误。该错误消息表明 Comms::Exception
class 是上面#2 的实例——也许它在 windows.h 尚未加载的地方使用?
其他我会代替你做的事情,就像例行公事一样:
1)确保我的包含路径和库路径不包含任何我不期望的内容。
2) 执行“构建清理”,然后手动验证它,如有必要,删除任何额外的目标文件。
3) 确保 include 语句中不存在任何与项目最初重建时的含义不同的硬编码路径。
编辑:与格式作斗争:(
其他提示
@柯特:我认为你是最接近的。我还没有测试过这个,但我想我在最初的问题中给出了答案。
获取消息 是 Windows.h 中包装在 ifndef 块中的定义,用于在 Ansi (GetMessageA) 和 Unicode (GetMessageW) 之间切换。
假设您没有在项目设置中删除您不应该拥有的东西(这是我期望像 User32.lib 这样的外部依赖项的地方):
检查工具|选项|目录|图书馆(从这里的记忆出发),并确保您不会错过普通的多种多样性lib目录(同样,我面前没有VC6,我无法告诉您它们是什么)
这是 Microsoft 处理 ANSI 与 ANSI 的方式的一个普遍问题。Unicode API。由于它们全部(或几乎全部)都是通过为解析为函数名称的“A”或“W”版本的函数名称定义宏来完成的,因此您无法在命名空间/类/结构/枚举/中安全地拥有标识符与 Windows API 名称匹配的函数。
windows.h 宏对所有其他命名空间都粗暴地运行。
windows.h 在 IOCompletionPort.h 的顶部声明为包含 - 我厌倦了看到 7 行只是包含 1 个文件,因此我将其包装为自己的文件并包含它本身。这还包含一些额外的#defines(即 ULONG_PTR),因为我们的主应用程序不会在安装了 Platform SDK 的情况下进行编译:-(
- 这已得到证实。没有什么是不合适的。
- 我已经做到了 - 删除了构建目录
- 我从不使用硬编码路径。