4

在发布模式下构建后,我看到了在调试模式下没有发生的异常。在调试发布版本时,看起来字符串引用没有正确地从 EXE(我们的应用程序)传递到接收字符串引用的 DLL。

我们的 EXE 代码如下所示:

string contents = "handle_message(): received=" + msg->encode();
LOG4CXX_DEBUG(logger, contents);

LOG4CXX_DEBUGis going to ,其log4cxx.dll代码如下所示:

CharMessageBuffer& CharMessageBuffer::operator<<(const std::basic_string<char>& msg) {
   if (stream == 0) {
      buf.append(msg);
   } else {
      *stream << msg;
   }
   return *this;
}

查看调试器中的调用堆栈,当我向下导航到包含源代码的框架时,我可以看到这contents是一个有效的字符串,带有size=583, capacity=838.

log4cxx.dll(堆栈中的下一帧)内部的帧中,字符串引用显示 size=838, capacity=363113231(并且值都是垃圾)。

我们的应用程序和 log4cxx.dll 都在同一台机器上编译,使用相同的运行时设置 (/MD),但 Visual Studio 版本不同。log4cxx dll 使用 Visual Studio 2008 编译,我们的应用程序使用 Visual Studio 2010 编译。在 2 个对象上运行 dumpbin 显示:

我们的应用程序 (EXE)

MSVCP100.dll
MSVCR100.dll

log4cxx.dll (DLL)

MSVCP90.dll
MSVCR90.dll

这个问题是因为他们使用不同的运行时版本吗?

4

2 回答 2

5

如果您在 DLL/EXE 边界(如 STL 字符串或 CRT 文件指针)之间传递非 POD(普通旧数据类型),则必须使用相同的共享CRT。

在您的情况下,您必须使用相同的编译器重新编译所有 DLL/LIB!

另请参阅:我可以为 Dll 传递 std::string 以及我可以用 DLL 做什么?

于 2013-08-02T20:38:55.443 回答
1

隐含的问题是:“有没有办法将数据(希望使用字符串和其他 STL 容器)传递给另一个版本的 Visual Studio 的 DLL,无论是在我使用的版本之前还是之后?”。

除了使用 POD 之外,可能还有三种方法:共享内存、套接字(到本地主机)和 MSMQ。所有这些方法都需要额外的大量编程,但更深层次的答案在于接口如何更改输入参数。

我在互联网上找到了字符串传递问题的可能解决方案。它消除了一层腐败;将指向容器的指针强制转换为 uint 并传递 uint。将 uint 取消引用到指针并显示对象。注意,auto_ptrs 通常会在这个过程中被删除,所以不要使用它们。如果传递的对象仍然偏移不正确(这发生在我身上,VS08 传递到 VS13 ),然后传递字符串的 c_str() 。这当然不优雅,但我们需要知道所有的替代方案。请参阅代码项目(2012 年 11 月 22 日)中的“操作方法:从 DLL 导出 C++ 类”。

于 2013-12-23T22:56:54.423 回答