【问题标题】:Dealing with an object corrupting the heap处理破坏堆的对象
【发布时间】:2010-11-13 01:46:23
【问题描述】:

在我的应用程序中,我正在创建一个非常像这样的对象:

connect() {
  mVHTGlove = new vhtGlove(params);
}

一旦我即将关闭应用程序,我就称之为:

disconnect() {
  if (mVHTGlove) 
    delete mVHTGlove;
}

此调用总是触发带有以下消息的断点:

Windows 在 DesignerDynD.exe。

这可能是由于 堆,表示存在错误 DesignerDynD.exe 或它的任何 DLL 已加载。

这也可能是由于用户 在 DesignerDynD.exe 时按 F12 有焦点。

输出窗口可能有更多 诊断信息。

我无法修改 vhtGlove 类来修复堆栈的损坏,因为它是一个仅以头文件、lib 文件和 dll 形式提供的外部库。

有什么方法可以干净利落地使用这个类吗?


**** 编辑 ::: 我试图将事情精简到最低限度,但是我得到了相同的结果...这里有整个代码。

#include "vhandtk/vhtCyberGlove.h"
#include "vhandtk/vhtIOConn.h"
#include "vhandtk/vhtBaseException.h"

using namespace std;

int main(int argc, char* argv[])
{
   vhtCyberGlove* testGlove = NULL;

   vhtIOConn gloveAddress("cyberglove", "localhost", "12345", "com1", "115200");
   try
   {
      testGlove = new vhtCyberGlove(&gloveAddress,false);

      if (testGlove->connect())
         cout << "Glove connected successfully" << endl;
      else
      {
         throw vhtBaseException("testGlove()->connect() returned false.");
      }

      if (testGlove->disconnect())
      {
         cout << "Glove disconnected successfully" << endl;
      }
      else 
      {
         throw vhtBaseException("testGlove()->disconnect() returned false.");
      }

   }
   catch (vhtBaseException *e)
   {
      cout << "Error with gloves: " << e << endl;
      system("pause");
      exit(0);
   }

   delete testGlove;

   return 0;
}

删除手套后仍然崩溃。


EDIT #2 :: 如果我只是分配和删除 vhtCyber​​Glove 的一个实例,它也会崩溃。

int main(int argc, char* argv[])
{
   vhtCyberGlove* testGlove = NULL;
   vhtIOConn gloveAddress("cyberglove", "localhost", "12345", "com1", "115200");
   testGlove = new vhtCyberGlove(&gloveAddress,false);
   delete testGlove; //<<crash!
   return 0;
}

有什么想法吗?

谢谢!

JC

【问题讨论】:

  • 请注意,您不需要检查 mVHTGlove 是否为 NULL。将 NULL 指针传递给 delete 是很好的定义。
  • disconnect() 调用了多少次?
  • 如果一个简单的 new 和 delete 崩溃,那么您使用的库似乎有缺陷。或者,您的编译器创建的运行时环境与库所期望的环境之间可能存在一些不匹配。我在这里有点含糊,但我看到由于未正确链接而出现奇怪的错误。
  • 感谢您的接受,但为什么呢?我很好奇这是怎么做到的。
  • 啊.. 好吧,我刚刚注意到我没有接受这个问题的任何答案,而且你的答案对于给定的信息来说已经足够完整了!该库要么自己处理指针(看到我使用 new 运算符创建对象会很奇怪),要么它们破坏了堆栈。这对我的应用程序来说并不重要,我现在还有很多其他的工作要做:)另外,在接下来的几个月里应该随时都有新版本的 API!

标签: c++ heap-memory heap-corruption fault-tolerant-heap


【解决方案1】:

一种可能性是 mVHTGlove 没有被初始化为 0。如果在没有调用连接的情况下调用了断开连接,那么您将尝试释放垃圾指针。轰隆隆。

另一种可能性是您实际上在该点之前损坏了堆栈,但那是损坏实际上导致崩溃的地方。一个很好的检查方法是尽可能多地注释掉代码并且仍然让程序运行,然后看看你是否仍然得到损坏。如果你不这样做,请慢慢带回一些代码,直到你看到它回来为止。


一些进一步的想法(在您的编辑之后)。

您可以检查一下 API 是否没有自己的内存管理调用,而不是期望您手动“新建”和“删除”对象。我这么说的原因是我看到一些 DLL 的问题看起来很像这样,当一些内存在 DLL 内部和一些外部进行管理时。

【讨论】:

  • 我制作了一个精简版的应用程序来严格测试这个模块并且......不。不过还是谢谢。
【解决方案2】:

删除vhtGlove时报堆损坏错误。但是,也可能是您自己的代码导致损坏。这通常是由于覆盖在堆上分配的缓冲区而发生的,可能来自对malloc 的调用。或者您可能会删除同一个对象两次。您可以通过使用像std::auto_ptr 这样的智能指针来存储指向对象的指针来避免这种情况。

【讨论】:

    【解决方案3】:

    当检测到堆损坏时,您可能会尝试追踪损坏源的一件事是使用 Visual Sudio 的“内存”窗口查看 mVHTGlove 指向的内存位置。看看您是否在该内存中看到任何看起来明显像溢出缓冲区的东西。例如,如果您看到程序中其他地方使用了一个字符串,那么请查看操作该字符串的代码——它可能会超出其缓冲区。

    【讨论】:

      【解决方案4】:

      鉴于 vhtCyber​​Glove 的实现在另一个 DLL 上,我会寻找堆不匹配。例如,在 VS 中,如果 DLL 链接到 Release CRT,而您的 EXE 链接到 Debug CRT,就会发生这种情况。在这种情况下,每个模块使用不同的堆,一旦您尝试使用错误的堆释放内存,就会崩溃。

      在您的情况下,vhtCyber​​Glove 可能会获得一些分配在另一个 DLL 上的东西,但是当您删除 vhtCyber​​Glove 实例时,这些东西会被直接删除,即指的是您的堆而不是 DLL。当试图释放指向另一个堆的指针时,你实际上破坏了你的。

      如果确实如此,在没有更多细节的情况下,我可以提供两个修复:

      1. 确保您的 EXE 使用与 DLL 相同的堆。可能会将您锁定在发布模式,所以这不是最好的方法
      2. 让 vhtCyber​​Glove 的提供者正确管理其内存使用...

      【讨论】:

      • 感谢您的回答。确实存在不匹配,vhtCyber​​Glove 链接到 MSVCRT,而我的应用程序链接到 MSVCRT90D(自然是因为我在调试中运行它)。但是,我不太确定这有多重要。我的意思是我在发布版本中使用了大量与调试模式应用程序相关联的库,但我从未注意到任何特定问题,我只是无法调试选定的代码片段。为什么现在会有所不同?
      • 这取决于 vhtCyber​​Glove。首先,在发布模式下尝试该代码,看看问题是否消失。如果是这样,那就是原因。没有看到更多代码很难说,但我会好好看看头文件。如果它包含函数定义,它们的代码将使用您的(调试)堆。如果 c'tor 全部在 DLL 中并且它分配了一些内存,并且 d'tor 在标头中,试图释放该内存,你会崩溃。如果是这样,这只是对 vhtCyber​​Glove 提供程序的糟糕编程。良好的 API 应该确保不会发生这种情况,我想到目前为止你一直很幸运。
      【解决方案5】:

      您将本地 vhtIOConn 的地址传递给构造函数。对象是否有可能取得了这个指针的所有权并试图在析构函数中删除它?

      【讨论】:

      • 我尝试动态分配 vhtIOConn 并将指针传递给构造函数,但它没有帮助。另外,我对 vhtIOConn 对象也有同样的问题。如果我只是创建它并在后面的行中删除它,bam crash。
      • 那就缩小范围了。听起来两个不同的堆是可能的答案。
      猜你喜欢
      • 1970-01-01
      • 2017-12-25
      • 1970-01-01
      • 2010-12-25
      • 1970-01-01
      • 1970-01-01
      • 2021-07-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多