【问题标题】:'TypeInfo<char>(char *)' isn't defined but worked pre-C++11; what changed, and how can I fix the error?'TypeInfo<char>(char *)' 未定义,但在 C++11 之前工作;发生了什么变化,我该如何解决这个错误?
【发布时间】:2014-07-04 20:39:42
【问题描述】:

我正在尝试从 Crysis Wars SDK 的源代码构建一个 DLL,并且过去曾在 Visual Studio 的早期版本(即 2005、2008 和 2010)上成功完成此操作。 我的具体问题是这样的:

Error   4   error LNK2019: unresolved external symbol "struct CTypeInfo const & __cdecl
TypeInfo<char>(char *)" (??$TypeInfo@D@@YAABUCTypeInfo@@PAD@Z) referenced in function 
"void __cdecl SwapEndian<char>(char *,unsigned int)" (??$SwapEndian@D@@YAXPADI@Z)   
G:\Noctis\Mods\Noctis\Code\GameCVars.obj    GameDll

我已尝试在 Visual Studio 中清理代码并重新构建它,以防万一这会起作用,但这并没有改变任何东西。

我在这里遗漏了什么,或者从 C++03 到 C++11 有什么变化,这意味着如果不恢复到旧版本的 C++,这段代码就不再可编译?

我已经在 Visual Studio 2010 上成功编译了 64 位和 32 位的这段代码,所以它一定是与将项目迁移到 Visual Studio 2015 相关的一些问题。

在 2012、2013 和 2015 版本的 Visual Studio 上编译会重现此错误,但不会重现 2010,因此似乎在 C++11 中引入了触发此问题的更改。

我做错了什么?

阅读mem-fun is not a member of std 的答案,可能只是我需要包含一个我不需要包含在早期版本的 Visual Studio 中的标准库。 如果这是真的,我需要哪个库#include

我也有created a GitHub repository containing only the original unmodified code provided from the SDK,用于测试目的(如果我自己打错了,这里似乎不是这种情况,但我把链接放在这里可能会有所帮助)。

如果重要的话,我在 Windows 10 Professional x64 上使用 Visual Studio 2015 企业版。

【问题讨论】:

  • 请求重新打开问题。尽可能多地添加细节,并包含一个包含我正在处理的代码的 GitHub 存储库,因此可以重现问题。
  • 您的证据表明问题是由 VS2012 引入的,而不是 C++11 本身。
  • @MM 证据表明是 C++11 导致它(作为 VS2010 和 VS2012 之间的主要变化),因为代码完美地编译为 C++03 而不是 C++11(可能虽然错了)。如果需要进一步确认,代码就在那里。
  • 你可以尝试创建一个新的项目文件;升级旧项目文件有时会做一些奇怪的事情
  • TypeInfo&lt;char&gt;(char*) 等在 CryCommon 项目 AutoTypeInfo.cpp 中定义。问题是 GameDll 编译得很好——它正确地找到了相关的 .h 文件,但是当它开始链接时,CryCommon 依赖项没有正确链接并导致错误。很难做出更多猜测,因为您的项目处于奇怪的状态(.sln 引用 .vcprojx,但仅签入 .vcproj 文件;有诸如#ifdef USE_&lt;unordered_map&gt; 之类的损坏的东西...)确保已构建 CryCommon 项目并它被 GameDll 引用为依赖项(作为库添加)。

标签: c++ c++11 visual-studio-2015 c++03


【解决方案1】:

错误是什么意思?

错误消息提示典型的“已声明但未定义”场景。

TypeInfo&lt;char&gt;(char*) 在 TypeInfo.h 中声明(通过一些宏)并在 CryCommon 项目的 AutoTypeInfo.cpp 中声明。

通常您只需确保正确构建 CryCommon 项目并正确链接到最终的 GameDll 项目即可。

但事实证明,CryCommon 项目已经很久没有构建了——它引用了许多其他 Crytek 库等。所以问题一定是现在需要这些 TypeInfo&lt;&gt; 定义而以前不需要。

什么是引用TypeInfo&lt;&gt; 代码?

在您的项目中,它是 Aurora/Code/GameCVars.cpp 中的函数 CmdHelp(),正是这一行:

nRead = gEnv->pCryPak->FRead( buf, BUFSZ, f );

FRead()方法的实现在CryCommon/ICryPak.h:

template<class T>
size_t FRead(T *data, size_t elems, FILE *handle, bool bSwap = true)
{
    size_t count = FReadRaw(data, sizeof(T), elems, handle);
    if (bSwap)
        SwapEndian(data, count);
    return count;
}

如您所见,如果bSwap 为真(默认),则在此处调用SwapEndian()

为什么以前没有表现出来?

也许编译器的行为确实不同。

或者,更有可能的是,您以前一直将项目编译为 Release。整个字节交换功能仅在大端系统(并且您的目标很可能不是其中之一)或调试期间启用 - 然后字节实际上被交换两次以测试相关代码(参见 CryCommon/Endian.h) .

可以做些什么来修复它?

你现在有几个选择:

  • 继续编译为发行版(可能和以前一样)。也许你永远不会在调试器中调试代码。

  • 只需将 FRead() 代码中的交换调用注释掉即可。无论如何,您都在使用它来加载文本文件,没有必要交换字符。

  • ...


FWIW,我必须做的其他事情才能使您的代码编译:

  • 查看“Broken”之前的早期提交
  • 加载 Mods\Aurora\Code\Aurora.sln
  • 删除不存在的 .vcprojx 项目
  • 再次添加所有 3 个 .vcproj 文件,让它们转换为 VS2015 的文件
  • 对于 GameDll 项目,添加预处理器定义_SILENCE_STDEXT_HASH_DEPRECATION_WARNING
  • 对于 GameDll 项目,设置启用 C++ 异常处理/EHsc
  • 注释掉上面的代码

【讨论】:

  • 这很准确,谢谢!似乎 Visual Studio 没有完全正确升级项目(可以通过安装 Visual Studio 2005 到 2015 的所有版本并在每个版本中升级项目来修复,而无需编辑代码)。我明天会奖励赏金(必须等待 21 小时)。
  • 嗯,是的,正如 M.M 上面所说,当心 VS 项目升级时,必须始终重新检查所有内容 - 或者最好从头开始一个新项目并避免任何遗留设置。无论如何,我很高兴你的东西正常工作!
猜你喜欢
  • 2018-07-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-21
  • 1970-01-01
  • 2021-11-25
  • 2016-02-22
  • 2015-06-13
  • 1970-01-01
相关资源
最近更新 更多