新对象会导致堆损坏

new object causes corruption on the heap

本文关键字:损坏 对象 新对象      更新时间:2023-10-16

几天来,我一直在与堆损坏问题作斗争。vs2005调试器首先警告我,在删除了以前新建的对象后,我可能已经损坏了堆。对这个问题的研究让我想到了gflags和页面堆设置。在为我的特定图像启用此设置后,它应该会将我指向实际导致腐败的行。

Gflags将问题对象的构造函数标识为罪魁祸首。对象派生如下:

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

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

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

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

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

从2005年与2005年的内存窗口挖掘来看,似乎没有为实际对象分配足够的空间。我的猜测是,只为基类分配了足够的资源。

导致故障的线路:

BusinessLogicUnit* biz = new MLUNumber();

我希望这可能是由于某种原因造成的,或者接下来的另一个故障排除步骤。

不幸的是,根据所提供的信息,无法明确诊断问题。

你可能想检查的一些东西:

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

如何删除内存?使用基类指针?你把BusinessLogicUnit的析构函数虚拟化了吗?它必须是virtual

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

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

BusinessLogicUnit不是MLUNumber。你为什么要这样分配?相反BusinessLogicUnit*biz=新BusinessLogicUnit();

或者你可能会这样做?

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)发生后立即死亡。。

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

通过启用检测(pageheap)来帮助您缩小问题范围,您做了正确的事情。我会继续沿着这条路走下去,找出导致访问违规的确切内存地址(以及地址来自哪里)。