【问题标题】:Release mode works fine but debug mode gives unhandled exception- using Octave DLLs发布模式工作正常,但调试模式使用 Octave DLL 提供未处理的异常
【发布时间】:2014-08-07 20:28:08
【问题描述】:

发布模式工作正常,但调试模式给了我这个:

Executable_to_LinkDLL_to_FDDDLL.exe 中 0x0fc5edac (msvcr90d.dll) 处未处理的异常:0xC0000005:访问冲突写入位置 0xbaadf00d。

我正在使用 Octave 版本的 DLL。异常如下所示。我想知道是否有人遇到过这个问题。

这是我的代码中发生错误的地方(基于以下调用堆栈):

【问题讨论】:

  • 我正在使用来自 Octave 的许多发行版 DLL...
  • @drescherjm 是否可以使用 Octave 库中的发布 DLL?
  • 除非他们隔离分配/解除分配,否则您可能会遇到使用超过 1 个独立堆的问题。请记住,您不能在 1 个堆中分配内存并在不同的堆中释放它。
  • @user3853917 - 发布 DLL 可用于调试版本。如果发布 DLL 不尝试传递或接受处理动态分配的内存的对象,就会出现这种情况。我不知道 Octave,但如果 Octave API 使用简单的参数类型,例如 LONG、DWORD 等,那么问题不在于 DLL。
  • @user3853917 - 嗯,要查找的简单事情是查看 Octave 是否在 DLL 和您的应用程序之间来回传递 std::string。如果是这样,那么您不仅需要匹配构建类型,还必须使用编译 Octave 库时使用的相同编译器版本。这就是跨模块边界来回传递 std::string 等对象的危险。

标签: c++ exception octave release-mode debug-mode


【解决方案1】:

查看 string_vector 的 Octave 文档,使用了对 std::string 的引用。这意味着需要为您正在开发的编译器和设置构建 Octave 库。

原因是std::string 等类不需要与std::string 的另一个版本二进制兼容。当您在调试版本中使用发布版本时,std::string 的内部结构在发布版本和调试版本中是不同的。

但是,即使std::string 的版本是二进制兼容的,您仍然会遇到确保 Octave DLL 和您的应用程序使用相同的运行时堆的问题。原因是std::string 使用动态分配的内存,并且必须为 DLL 和应用程序使用相同的堆。为确保这一点,必须使用 Visual Studio 运行时库的 DLL 版本(必须分别为 DLL 运行时的发布或调试版本设置 /MD/MDd 编译器标志)。

所以你有两个问题:

  1. Octave DLL 和您的应用程序之间的 std::string 版本之间的二进制兼容性,以及

  2. 确保构建 DLL 和应用程序以使用运行时库的 DLL 版本,以确保使用相同的内存堆。

您使用char * 的解决方案只能避免std::string 引用和对象被传递。我不知道这个解决方案有多可靠,因为似乎很容易出错并在某些时候调用std::string 函数。

我只是确保在开发和部署应用程序时使用正确的 DLL。这正是 Microsoft 对其 DLL 所做的事情——您不能在应用程序中混合和匹配 Microsoft DLL 的发布和调试版本,因此这里同样适用。唯一可以混合/匹配发布和调试 DLL 的情况是 DLL 仅使用“简单”类型(例如 DWORD、LONG、TSTR 等)或指向这些类型的指针作为参数和返回值。

【讨论】:

    【解决方案2】:

    调试器正在接收对未初始化内存的写入,该内存正被您的程序在发布模式下静默使用。 (即在发布模式下,这是一场等待发生的灾难。)0xbaadf00d 实际上是一种调试器消息;查看相关条目here

    如果没有看到您的代码,除此之外很难说出问题所在。

    编辑:您发布了引用memcpy 的调试输出--因此,您的代码中memcpy 的实例显然是一个值得一看的地方。

    【讨论】:

    • 谢谢。当我跟踪调用堆栈时,我看到这个异常发生在我正在使用的库中。
    • @user3853917 我从未使用过 Octave C 库,但我对 GSL 有很多经验,我相信它是基于它的——那里的许多函数都希望您自己分配内存例如工作区并将其作为参数传递给函数。我的猜测是您传递了一个尚未分配的工作区或输出参数——很容易犯错误。 Octave 本身存在问题的可能性较小,因为它是一个相当成熟的产品。
    • 我添加了一张新图片,显示当我想在我的 C++ 代码中使用 Octave 作为“嵌入式”引擎时发生此错误。在本地人中,“src”中有“嵌入”,可能是他们使用“char *”来传递“嵌入”吗?
    • @user3853917 由于分配了argv,我认为该图像中突出显示的行不是您的问题。
    • @user3853917 好的,那么() 运算符可能没有进行正确的分配。无论如何,这是一种不寻常的语法——我会查看string_vector 文档,也许会尝试找到另一种方法。
    【解决方案3】:

    windows LocalAlloc 用值 0xbaadf00d 标记未初始化的堆内存。 看起来您正在从未初始化的源获取指针值并尝试写入该内存位置。虽然这可能在发布模式下“起作用”,但它可能会导致运行时间较长的程序出现内存损坏。

    【讨论】:

    • 谢谢。当我跟踪调用堆栈时,我看到这个异常发生在我正在使用的库中。
    • @user3853917 可能是您为其提供了未初始化的参数。如果没有看到代码,我无法确定。我的建议是使用调试器逐步完成,并准确指出什么调用正在崩溃以及你传递给 dll 的内容。
    • 我添加了一张新图片,显示当我想在我的 C++ 代码中使用 Octave 作为“嵌入式”引擎时发生此错误。在本地人中,“src”中有“嵌入”,可能是他们使用“char *”来传递“嵌入”吗?
    【解决方案4】:

    我通过实现以下代码解决了这个问题。而不是使用八度音程的string_vector 类,现在我使用char* 的数组,例如char*argv[2]={"embedded","-q"};,因此错误已解决,但我遇到了此链接中提到的另一个错误:Octave c++ and VS2010

    【讨论】:

    • 我为您的问题添加了答案,还评论了您的解决方案,只要它可以走多远而不会遇到问题。
    • @PaulMcKenzie 谢谢。
    猜你喜欢
    • 2012-01-31
    • 1970-01-01
    • 1970-01-01
    • 2020-05-10
    • 2014-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多