其他分享
首页 > 其他分享> > c – 为什么向量删除析构函数是由于标量删除而被调用的?

c – 为什么向量删除析构函数是由于标量删除而被调用的?

作者:互联网

我有一些代码在大型系统中崩溃.
但是,代码基本上归结为以下伪代码.
我已经删除了很多细节,因为我试图把它煮到骨头上;
我不认为这会错过任何重要的事情.

// in a DLL:

#ifdef _DLL
#define DLLEXP __declspec(dllexport)
#else
#define DLLEXP __declspec(dllimport)
#endif

class DLLEXP MyClass // base class; virtual
{
public:
  MyClass() {};
  virtual ~MyClass() {};

  some_method () = 0; // pure virtual

  // no member data
};

class DLLEXP MyClassImp : public MyClass
{
public:
  MyClassImp( some_parameters )
  { 
    // some assignments...
  }

  virtual ~MyClassImp() {};

private:
  // some member data...
};

和:

// in the EXE:

MyClassImp* myObj = new MyClassImp ( some_arguments ); // scalar new
// ... and literally next (as part of my cutting-down)...
delete myObj; // scalar delete

请注意,正在使用匹配标量新标量和标量删除.

在Visual Studio(2008 Pro)中的Debug构建中,
在Microsoft的< dbgheap.c>中,
以下断言失败:

_ASSERTE(_CrtIsValidHeapPointer(pUserData));

靠近堆栈顶部的是以下项目:

mydll_d.dll!operator delete()
mydll_d.dll!MyClassImp::`vector deleting destructor'()

我认为这应该是

mydll_d.dll!MyClassImp::`scalar deleting destructor'()

也就是说,该程序的行为就像我写的那样

MyClassImp* myObj = new MyClassImp ( some_arguments );
delete[] newObj; // array delete

pUserData中的地址是myObj本身的地址(而不是成员).
该地址周围的内存如下所示:

                                ... FD FD FD FD
(address here)
VV VV VV VV MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
FD FD FD FD AB AB AB AB AB AB AB AB EE FE EE FE
...

其中四个VV可能是虚函数表的地址,
MM … MM是可识别的会员数据,
其他字节是调试器放置的各种特殊标记
(例如,FD FD是对象存储周围的“保护字节”).

断言失败前不久,我确实看到VV发生了变化,
并想知道这是否是由于切换到基类的虚函数表.

我知道正在进行破坏的类层次结构中的错误级别的问题.
这不是问题所在;我的析构函数都是虚拟的.

我注意到微软的页面
“BUG:错误的运算符删除调用导出的类”
http://support.microsoft.com/kb/122675
但这似乎是关于错误的可执行文件(错误的堆)试图承担破坏数据的责任.

就我而言,删除析构函数的错误“味道”似乎正在被应用:
即矢量而不是标量.

我正在尝试生成仍然存在问题的最小缩减代码.

但是,任何有助于如何进一步调查此问题的提示或技巧将非常感激.

也许这里最大的线索是堆栈上的mydll_d.dll!operator delete().
我应该期望这是myexe_d.exe!operator delete(),
表明DLLEXP已“丢失”?

我想这可能是双删除的一个实例(但我不这么认为).

有关_CrtIsValidHeapPointer检查的内容,我可以阅读一个很好的参考吗?

解决方法:

听起来像这可能是分配一个堆并尝试删除另一个堆的问题.从dll分配对象时,这可能是一个问题,因为dll有自己的堆.从您显示的代码看起来似乎不是这个问题,但可能在简化中丢失了一些东西?在过去,我看到这样的代码在对象上使用工厂函数和虚拟销毁方法,以确保在dll代码中发生分配和删除.

标签:c,destructor,debugging,visual-c,msvcrt
来源: https://codeday.me/bug/20191005/1857066.html