【问题标题】:Unable to pass std::wstring across DLL无法通过 DLL 传递 std::wstring
【发布时间】:2013-02-17 03:28:54
【问题描述】:

我在 Visual Studio 2010 中设置了一个项目来针对现有 MFC DLL 编写单元测试。我正在使用单头单元测试框架,并从单元测试项目链接到 MFC DLL 的 lib 包装器。我正在尝试构建一个在其构造函数中采用std::wstring 的类。这是我的测试的样子:

TEST_CASE("MyProject/MyTest", "Do the test.")
{
    MockDbService mockDbService;
    Foobar foo(L"{F00DFACE-FEED-DEAD-BEEF-C0FFEEDECADE}", mockDbService);

    foo.loadObject();

    REQUIRE(mockDbService.getMethodInvokeCount("query()") >= 1);
}

其中Foobar 是从被测 MFC DLL 导出的类。但是,测试框架报告了一个意外的异常。在将字符串复制到Foobar 的构造函数时,我将其追踪到std::wstring 的复制构造函数。 MSVC 调试器将源字符串报告为<Bad Ptr>

我创建了一个虚拟构造函数Foobar::Foobar(long num, IDbService& db),所有值(包括IDbService&)都可以正常显示。

MFC DLL 和我的单元测试 EXE 都共享一个属性表,该属性表应该保持编译器标志相同。我正在调试模式下构建和运行测试。任何想法为什么std::wstring 不能跨 DLL 复制?

【问题讨论】:

  • 您是否将 EXE 和 DLL 与 CRT 的调试版本动态链接? (/MDd)
  • @Mr.C64 哇,就是这样。我的单元测试项目使用/MD,而MFC DLL 是/MDd。我想要一个简短的解释作为答案,以便我能理解它;我会接受的。谢谢!
  • 我添加了一个简短的解释。基本上,我认为您的问题是 debug-build 的 std::wstring 与 release-build 的 std::wstring 具有不同的实现。

标签: c++ visual-studio-2010 visual-c++ dll


【解决方案1】:

您应该使用相同的调试 CRT/MDd 编译器选项)检查 EXE 和 DLL 是否动态链接。确保 EXE 和 DLL 的其他设置(如 _HAS_ITERATOR_DEBUGGING)也相同。

(一种快捷方式可以是在类接口处使用const wchar_t* 而不是std::wstring,然后从构造函数体内的原始指针构建一个std::wstring)。

编辑:您确认 CRT 不匹配(即使用 /MD 构建的 EXE 与使用 /MDd 构建的 DLL)是问题所在。事实上,同一个类名std::wstring 表示调试版本(/MDd)和发布版本(/MD)中的两个不同类。事实上,在调试版本中,类实现中可以有额外的机制来帮助调试;这种机制可能会导致效率低下,因此在发布版本中已将其删除。因此,调试版本的std::wstring 的内部结构与发布版本的std::wstring 不同(例如,如果您尝试打印std::wstring 实例的原始sizeof,您可以在发布版本和调试版本中找到不同的数字)。所以,用/MD 构建的EXE 期待release-build 的std::wstring;相反,使用/MDd 构建的 DLL 期望调试构建的 std::wstring:这两个期望之间不匹配(一个模块期望类 X,但另一个模块提供类 Y),所以你有一个崩溃。

【讨论】:

  • 这是有道理的。谢谢你。在这种情况下,我的问题正是我之前发现的问题:stackoverflow.com/questions/2322095/… 但是我的两个项目都是在 Debug 中构建的,所以我认为它不相关。根据您的说法,即使是调试项目,我也在使用 CRT 的发布版本。再次感谢。
  • 是的,/MD 是动态链接释放 CRT DLL; /MDd 是调试 CRT DLL 的动态链接。
猜你喜欢
  • 2019-04-07
  • 2014-04-12
  • 2019-05-14
  • 2014-01-05
  • 2012-11-24
  • 2018-08-29
  • 2011-06-19
  • 2016-01-20
  • 1970-01-01
相关资源
最近更新 更多