LNK2022元数据操作:重复类型中的不一致布局信息

16

我在处理一个项目时遇到了一个新的连接器错误:

1>MSVCMRTD.lib(locale0_implib.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std.basic_string<char,std::char_traits<char>,std::allocator<char> >): (0x0200004e).
1>MSVCMRTD.lib(locale0_implib.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std.basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >): (0x02000075).
1>MSVCMRTD.lib(locale0_implib.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std._String_iterator<char,std::char_traits<char>,std::allocator<char> >): (0x02000091).
1>MSVCMRTD.lib(locale0_implib.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std._String_const_iterator<char,std::char_traits<char>,std::allocator<char> >): (0x02000092).
1>MSVCMRTD.lib(locale0_implib.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std._String_val<char,std::allocator<char> >): (0x02000097).
1>MSVCMRTD.lib(locale0_implib.obj) : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (std._String_val<wchar_t,std::allocator<wchar_t> >): (0x02000099).

我们正在使用Windows 7中的Visual Studio 2010。

这个项目曾经编译过。它是一个C++/CLI DLL包装器,包含了一些非托管代码的公共语言运行时支持。发生了变化的是我们链接到的外部静态库被“更新”了。当我们尝试编译链接到它的项目时,就会出现这个错误。

微软为这个问题提供的“帮助”是“在对象文件上运行ildasm –tokens以查找哪些类型在error_message中列出了令牌,并查找差异”。然后我检查了this page,注意到/tokens选项仅适用于.exe和.dll文件...但这是一个链接器错误,所以我的.dll文件还没有生成!

我尝试运行像ildasm -tokens AssemblyInfo.obj之类的命令,但唯一发生的事情就是打开一个窗口,显示这个极其有用的错误消息:

Thanks Microsoft

感谢微软!

我不太确定如何继续解决这个问题。一个发布版本能正常工作——只有调试版本出了问题。所以我猜测在某个地方,std::string 类型的大小或者其他什么东西发生了变化……

有任何想法吗?


4
有时在更改头文件时,我会遇到这个错误,编译器没有重新编译所有应该编译的代码文件。你可能已经尝试过了,但清理并进行完整重建可能会有所帮助。 - David Yaw
@DavidYaw 感谢您的推荐 - 我一直在进行完全重建,但没有成功。不过我觉得我正在找到一些线索... - aardvarkk
3个回答

17

好了,问题解决了!下面是一个非常有用的SO问题,解决了我的问题。它链接到了这篇文章,详细介绍了问题。基本上,问题出在标准库字符串同时在托管和非托管代码中被编译的某些问题上。解决方案是仅在需要其支持的文件上启用CLR。具体来说,我做了以下几点:

  1. 删除应用于整个项目的/clr开关
  2. 选择实际需要CLR的两个.cpp文件,并在C/C++ -> General -> Common Language RunTime Support下手动选择/clr
  3. 将整个项目从Program Database for Edit and Continue /ZI切换到Program Database /Zi。这样做是为了消除警告,因为我认为/clr支持似乎会禁用增量链接,然后我的本地代码尝试使用“Edit and Continue”,所以产生了警告。
  4. 然后我收到了一些ExtensionAttribute警告,通过为我的启用/clr的文件添加以下开关解决了这些警告:/clr:nostdlib /AI"%ProgramFiles%\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0"
  • 在 Debug 版本中,我必须禁用 /clr 启用的文件上的一堆调试选项。具体来说,在 C/C++ -> 代码生成 下,我将 启用最小重建 设置为 No (/RM-),并将 基本运行时检查 设置为 默认。这也消除了一堆警告。
  • 在 Debug 和 Release 版本中,在 clr 启用的文件上将 启用 C++ 异常 设置为 No
  • 希望这能有所帮助!


    我遇到了同样的问题,但在我的情况下,对<string.h>的引用也需要在托管文件中(除非我们更改API)。是否有其他方法可以解决这个问题? - Kohanz
    1
    我唯一能推荐的是尝试通过使用动态链接库来分离托管/非托管代码,也许可以这样做?这对我有用,但我不确定它是否适用于所有情况... - aardvarkk
    这也是由于包含的 #define 之间存在差异,例如 WINVER_WIN32_WINNT 导致的。 - JB.
    我进行了反向操作,只针对不需要/clr的.cpp文件进行了停用。 - Matthew Grivich
    1
    @JohnGrabanski 删除了已经失效的链接...有点晚了。 - aardvarkk
    显示剩余2条评论

    2
    我的解决方法是设置配置属性 -> C/C++ -> 代码生成 -> 结构体成员对齐 -> 16 字节 (/Zp16)。

    这个解决方案曾经帮我解决了一个类似的问题,即重复类型中不一致的字段声明。 - Aak

    2

    看起来我的Visual Studio出了点问题。只有我一个人遇到了这个错误。 我没有做任何更改。 我在另一台电脑上重新检出项目,问题就解决了。 可能是我的用户文件出了问题。


    在我的情况下,我只是将 .vcxproj 从 VS2013 升级到了 VS2015。清理 -> 重建解决了这个问题。 - Overlord Zurg

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接