无法跨DLL传递std :: wstring

时间:2013-03-02 18:31:49

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

我在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导出的类。但是,测试框架会报告意外的异常。在将字符串复制到std::wstring的构造函数时,我将其跟踪到Foobar的复制构造函数。 MSVC调试器将源字符串报告为<Bad Ptr>

我创建了一个虚拟构造函数Foobar::Foobar(long num, IDbService& db),并且所有值(包括IDbService&)都很好。

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

1 个答案:

答案 0 :(得分:10)

您应该使用相同的调试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不同(例如,如果您尝试打印sizeofstd::wstring实例,可以找到不同的数字在发布版本和调试版本中)。因此,使用/MD构建的EXE期待发布版本std::wstring;相反,使用/MDd构建的DLL期望调试构建的std::wstring:这两个期望之间存在不匹配(一个模块期望类X但另一个模块正在提供类{{1}因此你崩溃了。