C++ delete操作报错(二)

在上篇   C++ delete操作报错(一) 中,讲到自定义对象在delete和delete []之间的区别,并且在VS报错的情况。

先讲一下delete和delete[] 的区别:

有个例子:

class CustomTest
{
public:
	CustomTest()
	{
	     a = 0;
	     cout<<"CustomTest 构造"<<a<<endl;
	}

	~CustomTest()
	{
	     cout<<"Custom 析构~"<<a<<endl;
	}

public:
	int a;
};


测试程序:

void NewDeleteTest()
{
	CustomTest* pBuf = NULL;
	int nTestCount  = 5;
	pBuf = new CustomTest[nTestCount];

	//init pBuf
	for (int i = 0; i < nTestCount; i++)
	{
		pBuf[i].a =i;
		cout<<"a = "<<pBuf[i].a<<endl;
	}

	CustomTest *pTest = pBuf+2;
	cout<<"pTest a = "<<pTest->a<<endl;

	delete []pBuf;  //delete pBuf   //区别就在这个地方---------------------------------------
	pBuf = NULL;
}


若使用的是delete pBuf,结果为:


若使用的是delete []pBuf ,结果为:


可以看到:

用delete,只是释放了一个Custom对象,但是数组中有五个对象,

用delete[], 五个Custom对象都释放了。

注:这个是用的codeBlock IDE, MinGW编译器,用它是因为不报错,好看结果,嘿嘿。

这边了解了一个基本问题,就是对于指向对象数组的指针,用delete,只会删除数组的第一个元素。

用delete[] 会将数组中的对象都释放掉。


好,现在讨论在VS下用delete删除一个对象数组指针时报错的问题。

根据报错,我们会跟到一个dbgdel.cpp文件中,

/* verify block type */
  _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));

先看一个数据结构定义:就是DEBUG下系统对内存进行管理的一个数据结构:

_CrtMemBlockHeader * pHead;

typedef struct _CrtMemBlockHeader
{
        struct _CrtMemBlockHeader * pBlockHeaderNext;
        struct _CrtMemBlockHeader * pBlockHeaderPrev;
        char *                      szFileName;
        int                         nLine;
 #ifdef _WIN64
        /* These items are reversed on Win64 to eliminate gaps in the struct
         * and ensure that sizeof(struct)%16 == 0, so 16-byte alignment is
         * maintained in the debug heap.
         */
        int                         nBlockUse;
        size_t                      nDataSize;
#else  /* _WIN64 */
        size_t                      nDataSize;
        int                         nBlockUse;
#endif  /* _WIN64 */
         long                        lRequest;
        unsigned char               gap[nNoMansLandSize];
        /* followed by:
         *  unsigned char           data[nDataSize];
         *  unsigned char           anotherGap[nNoMansLandSize];
         */
} _CrtMemBlockHeader;

可以看出来,这是一个双向的链表,(每一个结构中都包含一个pre和next指针)。 还包含如下信息: 申请空间的文件名、所在行数、用户申请的数据大小, 内存块的类型,用于内存管理信息的额外空间。

现在来看出错的断言:

/* verify block type */
 _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));

我们传进去的参数, pHead->nBlockUse的值为147 看看是如何判断一个内存块的是否是合法的。

#define _BLOCK_TYPE_IS_VALID(use) (_BLOCK_TYPE(use) == _CLIENT_BLOCK || \
                                              (use) == _NORMAL_BLOCK || \
                                   _BLOCK_TYPE(use) == _CRT_BLOCK    || \
                                              (use) == _IGNORE_BLOCK)

而BLOCK_TYPE(use)又是怎么的宏定义呢:

#define _BLOCK_TYPE(block)  (block & 0xFFFF)

我们的参数穿进去之后,还是147啊。 而
CLIENT_BLOCK    4
NORMAL_BLOCK    1
CRT_BLOCK       2
IGNORE_BLOCK    3

没一个条件能成立,所以断言不成立,系统就会弹出那么大的错误提示框。

但是为什么我们穿进去的参数会是147呢。这个我还要好好想想,哈哈

转载于:https://my.oschina.net/myspaceNUAA/blog/55763

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值