【问题标题】:crash with unexecuted code未执行的代码崩溃
【发布时间】:2012-03-30 01:19:07
【问题描述】:

我正在调试一个商业软件的插件。应用程序在按下退出按钮后立即崩溃。这些崩溃出现在 windows vista 64 sp2 或 vista 32(不记得是否是 sp)上,但不会出现在 windows xp sp3 上。根据应用程序生成的崩溃日志,我似乎有一些堆问题,所以我在激活页面堆的情况下进行调试。

几乎从零开始,我拿了一个插件示例代码,在其中我逐渐添加了我的代码。我的插件添加了一个按钮来创建我的工具。工具和按钮是两个独立的 COM 对象。始终会创建按钮,但仅当我按下按钮时才会创建工具对象。 现在,我在工具部分添加了一些代码,代码没有执行,甚至没有创建工具对象,但是程序崩溃了。没有那部分代码,它不会。它似乎不依赖于代码的那部分,当我对其进行注释并在其他地方添加一些代码(不会执行)时,程序以同样的方式崩溃。

adplus 告诉我:损坏的堆指针或使用错误的堆 xx : 调用中使用的堆 xx : 堆块 xx : 块大小 xx : 拥有区块的堆

我可以从任何想法或调试策略开始吗?

谢谢。

【问题讨论】:

  • 一些代码会很有用。一个简单的复制案例。

标签: c++ debugging com heap-memory


【解决方案1】:

提供代码示例总是有帮助的。

堆损坏确实很棘手,因为即使它是错误的,也可能无法检测到。因此,虽然您可能会以某种方式持续崩溃,但这并不意味着当您不崩溃时它就没有损坏。

无法附加的崩溃很可能是由于静态初始化引起的。当您附加 DLL 时,我会尝试手动初始化这些类型的资源。 DLL 分离时删除资源,并将指针设置为零。拥有可以处理此问题的“主要”静态函数。

您可能还对静态的初始化顺序做出了假设,这根本无法保证。更糟糕的是,它们会在很长一段时间内表现得相对一致,然后由于某种根本不明显的原因在看似随机的时间中断。

COM 对象的另一种可能性是您的二进制兼容性不再匹配调用代码所期望的接口。如果您正在实现的接口不是纯虚拟的,这可能是特别出乎意料的。如果接口有任何带有默认实现的方法,则需要覆盖它们。

struct foo_base {
  virtual ~foo_base() {}
  virtual std::string getName() const {
    return "Willem Dafoe";
  }
};

struct foo_derived : public foo_base {
  virtual ~foo_derived() {}
};

即使这是完全有效的 C++,它也可能无法用作 COM 对象。

如果您对血淋淋的细节不感兴趣,请为只调用基础的虚拟方法添加一个实现。

struct foo_base {
  virtual ~foo_base() {}
  virtual std::string getName() const {
    return "Willem Dafoe";
  }
};

struct foo_derived : public foo_base {
  virtual ~foo_derived() {}
  virtual std::string getName() const {
    return foo_base::getName();
  }
};

我个人从未见过来自此的堆损坏消息,但我见过它调用带有垃圾指针的方法。如果您尝试释放它,我可以看到可能在哪里被检测为堆损坏。

【讨论】:

    猜你喜欢
    • 2016-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-29
    • 2020-11-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多