2012-03-13 134 views
1

我正在调试商业软件的插件。按下退出按钮后,应用程序崩溃。这些崩溃出现在windows vista 64 sp2或vista 32(不记得是否是sp),但不在windows xp sp3上。根据应用程序生成的崩溃日志,看起来我有一些堆问题,所以我使用页堆激活进行调试。未执行代码崩溃

几乎从头开始,我采用了一个插件示例代码,在该代码中逐渐添加我的代码。我的插件添加了一个创建我的工具的按钮。该工具和按钮是两个独立的COM对象。该按钮始终创建,但只有按下按钮才能创建工具对象。 现在,我在工具部分添加了一些代码,代码没有执行,工具对象甚至没有创建,但程序崩溃。没有这部分代码,它不会。它似乎不依赖于代码的那部分,当我评论它并在其他地方添加一些代码(不会执行)时,程序崩溃的方式相同。

ADPlus的告诉我:损坏堆指针或使用错误的堆 XX:堆在呼叫 XX使用:堆块 XX:块大小 XX:堆拥有该块

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

谢谢。

+0

一些代码会很有用。一个简单的repro案例。 – Robinson 2012-03-13 18:58:45

回答

0

给代码示例总是有帮助。

堆损坏真的很棘手,因为即使它是错误的,它可能不会被检测到。所以虽然你可能会以某种方式持续发生崩溃,但这并不意味着当你没有崩溃时它不会崩溃。

由于静态初始化,崩溃而不能连接是合理的。我会尝试在连接DLL时手动初始化这些类型的资源。在DLL分离时删除资源,并将指针设置为零。有“主要”静态函数来处理这个,你可以进入。

您也可能会对静态的初始化顺序做出假设,但这并不是毫无保证的。更糟糕的是,他们会长时间表现相对一致,然后出于某种原因而看似随机的时间突然出现,这一点并不明显。

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

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(); 
    } 
}; 

我从来没有见过从这个人的堆腐败消息,但我看到它调用垃圾指针的方法。如果您试图释放它,我可以看到可能被检测为堆损坏。