2

几天来,我一直在努力解决堆损坏问题。vs 2005 调试器首先警告我,在删除我之前新建的对象后,我可能已经损坏了堆。对这个问题进行研究使我想到了 gflags 和页堆设置。在为我的特定图像启用此设置后,它应该将我指向实际导致损坏的行。

Gflags 将相关对象的构造函数识别为罪魁祸首。对象派生如下:

class POPUPS_EXPORT MLUNumber :  public MLUBase
  {
...
  }
class POPUPS_EXPORT MLUBase : public BusinessLogicUnit
  {
...
  }

我可以在单独的线程中实例化 MLUNumber,并且不会发生堆损坏。

我可以实例化一个不同的类,它也继承自 MLUBase,不会导致堆损坏。

由于构造函数的左大括号上发生损坏而引发访问冲突,这似乎是因为对象的隐式初始化(​​?)。

基类构造函数 (MLUBase) 成功完成。

通过挖掘 vs 2005 中的内存窗口,似乎没有为实际对象分配足够的空间。我的猜测是只为基类分配了足够的空间。

导致故障的线路:

BusinessLogicUnit* biz = new MLUNumber();

我希望是出于可能导致此问题的原因,或者是另一个故障排除步骤。

4

5 回答 5

6

不幸的是,根据给出的信息,无法明确诊断问题。

您可能需要检查的一些事项:

  • 确保 BusinessLogicUnit 具有虚拟析构函数。当delete通过基指针 ing 对象时,虚拟析构函数必须存在于基类中,才能正确析构子类。
  • 确保您使用相同的预处理器标志和编译器选项构建所有源文件。标志的差异(可能在调试/发布标志之间?)可能导致结构大小发生变化,从而导致不同源文件中报告的大小不一致。
  • 即使使用 gflags 设置,某些类型的堆损坏也可能未被检测到。审核您的其他堆使用以尝试找出问题的根源。理想情况下,您应该组合一个最小的测试用例,该用例将可靠地崩溃,但活动量最少,这样您就可以缩小原因。
  • 尝试一个干净的解决方案并重建;我偶尔会看到时间戳被搞砸了,旧的目标文件可能会包含过时的结构定义。至少值得检查:)
于 2011-06-24T19:53:54.757 回答
2
BusinessLogicUnit* biz = new MLUNumber();

怎么删除内存?使用基类指针?你做了BusinessLogicUnitvirtual的析构函数吗?一定是virtual

class BusinessLogicUnit
{
  public:
      //..
      virtual ~BusinessLogicUnit(); //it must be virtual!
};

否则,根据 C++ 标准,通过基类指针删除派生类对象会调用未定义的行为。

于 2011-06-24T19:52:29.843 回答
0

BusinessLogicUnit不是MLUNumber。为什么要这样分配?而是 BusinessLogicUnit* biz = new BusinessLogicUnit();

于 2011-06-24T19:48:24.980 回答
0

或者也许你会做这样的事情?

struct A
{
    SomeType & m_param;

    A(SomeType & param) : m_param(param)
    {
        ...use m_param here...
    }
};

A a(SomeType()); // passing a temporary by reference

那是未定义的行为,因为引用的临时对象在m_param(param)发生后立即死亡..

于 2011-06-24T19:56:08.317 回答
0

我同意 bdonlan 的观点,即没有足够的信息来找出问题所在。这里有很多很好的建议,但仅仅猜测应用程序崩溃的可能原因并不是解决问题的明智方法。

通过启用检测(pageheap)来帮助您缩小问题范围,您已经做了正确的事情。我将通过准确找出导致访问冲突的内存地址(以及地址来自何处)继续沿着这条路走下去。

于 2011-06-24T20:31:18.330 回答