为什么矢量删除析构函数被调用作为标量删除的结果? [英] Why is vector deleting destructor being called as a result of a scalar delete?

查看:203
本文介绍了为什么矢量删除析构函数被调用作为标量删除的结果?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些在大型系统中崩溃的代码。
然而,代码基本上归结为以下伪代码。
我已经删除了大部分的细节,因为我已经尝试把它烧成裸露的骨头;
我不认为这没有任何关键的东西。

  //在DLL中:

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

class DLLEXP MyClass //基类; virtual
{
public:
MyClass(){};
virtual〜MyClass(){};

some_method()= 0; // pure virtual

// no member data
};

class DLLEXP MyClassImp:public MyClass
{
public:
MyClassImp(some_parameters)
{
//某些作业...
}

virtual〜MyClassImp(){};

private:
//某些成员数据...
};

和:

 code> //在EXE中:

MyClassImp * myObj = new MyClassImp(some_arguments); //标量新
// ...和字面上下一个(作为我的裁剪的一部分)...
删除myObj; //标量删除

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



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

  _ASSERTE(_CrtIsValidHeapPointer(pUserData)); 

堆栈顶部附近有以下项目:

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

我认为这应该是

  mydll_d .dll!MyClassImp ::`标量删除析构函数'()

也就是说,程序的行为如果我写了

  MyClassImp * myObj = new MyClassImp(some_arguments); 
delete [] newObj; //数组删除

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

  ... FD FD FD FD 
(地址这里)
VV VV VV VV MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
FD FD FD FD AB AB AB AB AB AB AB EE FE EE FE
...
/ pre>

其中四个 VV 可能是虚拟函数表的地址,
MM ... MM 是可识别的成员数据,
,其他字节是调试器
(例如$ code> FD FD 是对象存储周围的'保护字节')。



在断言失败前不久我看到了 VV s更改,
,并怀疑是否由于切换到基类的虚拟功能表。



我意识到类层次结构中错误级别的问题正在遭到破坏。
这不是这里的问题;我的析构函数都是虚拟的。



我注意到微软的页面
BUG:错误的操作符删除调用导出类
http://support.microsoft.com/kb/122675
但似乎是关于错误的可执行文件(错误的堆)试图对数据的销毁负责。



在我的情况下,删除析构函数的错误风味似乎被应用:
即向量而不是标量。



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



但是,有关如何进一步调查此问题的任何提示或提示将不胜感激。



也许最大的线索是栈上的 mydll_d.dll!operator delete()
我应该期望这是 myexe_d.exe!operator delete()
表示 DLLEXP s已经丢了?



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

有没有一个很好的参考,我可以阅读哪些 _CrtIsValidHeapPointer 检查?

解决方案

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


I have some code that is crashing in a large system. However, the code essentially boils down to the following pseudo-code. I've removed much of the detail, as I have tried to boil this down to the bare bones; I don't think this misses anything crucial though.

// 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...
};

and:

// in the EXE:

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

Note that matching scalar new and scalar delete are being used.

In a Debug build in Visual Studio (2008 Pro), in Microsoft's <dbgheap.c>, the following assertion fails:

_ASSERTE(_CrtIsValidHeapPointer(pUserData));

Near the top of the stack are the following items:

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

I think this ought to be

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

That is, the program is behaving as if I'd written

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

The address in pUserData is that of myObj itself (as opposed to a member). The memory around that address looks like this:

                                ... 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
...

where the four VVs are presumably the address of the virtual function table, the MM...MM is recognisable member data, and the other bytes are various special markers put in place by the debugger (e.g. the FD FDs are 'guard bytes' around the object's storage).

Shortly before the assertion failure I do see the VVs change, and wonder if that is due to a switch to the base class's virtual function table.

I'm aware of the problem of the wrong level in the class hierarchy undergoing destruction. That's not the problem here; my destructors are all virtual.

I note Microsoft's page "BUG: Wrong Operator Delete Called for Exported Class" http://support.microsoft.com/kb/122675 but that seems to be regarding the wrong executable (with the wrong heap) attempting to take responsibility for destruction of the data.

In my case, it's that the wrong 'flavour' of deleting destructor appears to be being applied: i.e. vector rather than scalar.

I am in the process of trying to produce minimal cut-down code that still exhibits the problem.

However, any hints or tips to help with how to investigate this problem further would be much appreciated.

Perhaps the biggest clue here is the mydll_d.dll!operator delete() on the stack. Should I expect this to be myexe_d.exe!operator delete(), indicating that the DLLEXPs have been 'lost'?

I suppose this could be an instance of a double-delete (but I don't think so).

Is there a good reference I can read regarding what _CrtIsValidHeapPointer checks for?

解决方案

Sounds like this could be an issue of allocating off of one heap and trying to delete on another. This can be an issue when allocating objects from a dll as the dll has its own heap. From the code you're showing it doesn't seem like this would be the problem but maybe in the simplification something was lost? In the past I've see code like this use factory functions and virtual destroy methods on the objects to make sure that the allocation and deletion happens in the dll code.

这篇关于为什么矢量删除析构函数被调用作为标量删除的结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆