游戏开发论坛

 找回密码
 立即注册
搜索
查看: 5002|回复: 14

VC中的delete和delete[]

[复制链接]

89

主题

822

帖子

847

积分

高级会员

Rank: 4

积分
847
发表于 2006-1-12 19:32:00 | 显示全部楼层 |阅读模式
很多人在考虑delete和delete[]总是区分基本数据类型和用户自定义类型

但是我发现并非如此

int * p = new int[100];
我们调用delete p和delete[] p并没有任何问题,也检查不出内存泄漏

class A
{
public:
    int a;
    A( ) { }
};

A * p = new A[100];
我们调用delete p和delete[] p同样也没有任何问题,也检查不出内存泄漏

class A
{
public:
    int a;
    A( ) { }
    ~A( ) { }
};
A * p1 = new A[100];
A * p2 = new A;
我们调用delete p2和delete[] p1也没有任何问题,没有内存泄漏

但是我们调用delete p1和delete[] p2就立即出错

跟踪发现
void* __cdecl operator new[](size_t nSize, int nType, LPCSTR lpszFileName, int nLine)
{
        return :perator new(nSize, nType, lpszFileName, nLine);
}
void __cdecl operator delete[](void* p)
{
        ::operator delete(p);
}
从上面的代码来看,new[]就是调用了new,delete[]也同样就是调用delete,为什么会出错呢,检查发现Debug下VC做了一些CRT断言,问题就出在_CrtIsValidHeapPointer这个函数上,这个函数是有源代码的,但不能跟踪无法发现错误,只能看到该函数返回出栈时出错。

那原因究竟在哪?

大家可以看到问题就在那个定义了的析购函数上。

还是继续跟踪有析购函数和无析购函数的情况
class A // 有析购函数
{
public:
    int a;
    A( ) { }
    ~A( ) { }
};
class B // 无析购函数
{
public:
    int b;
    B( ) { }
};

A * p1 = new A[1];
A * p2 = new A;

B * p3 = new B[1];
B * p4 = new B;

跟踪进去,你会发现
p1申请了8个字节
p2申请了4个字节
p3申请了4个字节
p4申请了4个字节

而p1使用delete直接删除就会出错,原因是内存长度不一致,那么多出来的这4个字节做什么用呢,我并没有继续跟下去,我想我差不多能猜出来了,这多出来的指针 。。。

20

主题

398

帖子

398

积分

中级会员

Rank: 3Rank: 3

积分
398
发表于 2006-1-13 09:54:00 | 显示全部楼层

Re:VC中的delete和delete[]

有道理!

18

主题

279

帖子

279

积分

中级会员

Rank: 3Rank: 3

积分
279
QQ
发表于 2006-1-13 10:25:00 | 显示全部楼层

Re:VC中的delete和delete[]

多出来的数据是用来帮助“自销毁”的。

也就是说可以这样做:
class CYourClass
{
public:
CYourClass( ) { }
~CYourClass( ) { }
void Release( ) { this->~CYourClass( ); }
};

CYourClass one;
CYourClass *two = new CYourClass( );

one.Release( );
two->Release( );

它们都可以被正确销毁,而且two在堆上的内存也会被正确释放。

3

主题

7

帖子

9

积分

新手上路

Rank: 1

积分
9
发表于 2006-1-13 17:56:00 | 显示全部楼层

Re:VC中的delete和delete[]

大哥,我怎么认为应该不是8呢,除非你析构函数是虚的。。。

15

主题

90

帖子

90

积分

注册会员

Rank: 2

积分
90
发表于 2006-1-13 18:18:00 | 显示全部楼层

Re:VC中的delete和delete[]

不管他会不会出错我们都应该配队使用new和delete
否则你换一个编译器编译程序可能就会出问题  哈

132

主题

1341

帖子

1341

积分

金牌会员

Rank: 6Rank: 6

积分
1341
发表于 2006-1-14 17:27:00 | 显示全部楼层

Re: Re:VC中的delete和delete[]

bombbear: Re:VC中的delete和delete[]

多出来的数据是用来帮助“自销毁”的。

也就是说可以这样做:
class CYourClass
{
public:
CYourCla...

我们能调用析构函数?

18

主题

279

帖子

279

积分

中级会员

Rank: 3Rank: 3

积分
279
QQ
发表于 2006-1-15 11:10:00 | 显示全部楼层

Re:VC中的delete和delete[]

TO [B]hdm2968[/B]:
调用析构函数是没有问题的(注意我的用法),但是能正确释放堆上的内存我只在VC上实验过。
我想大多数在PC上的编译器都没有问题,因为很多编译器都会在分配内存时添加附加信息,但由于C++标准并不假定存在这些信息,所以这种做法并不保险。

13

主题

978

帖子

978

积分

高级会员

Rank: 4

积分
978
发表于 2006-1-15 18:02:00 | 显示全部楼层

Re:VC中的delete和delete[]

是不是可以这样理解:无论是否有析构函数,都会有一个系统预设计的release()来析构。而写了自己的析构函数后(无论这个函数是不是空的),都会调用release和自定义的析构函数?

132

主题

1341

帖子

1341

积分

金牌会员

Rank: 6Rank: 6

积分
1341
发表于 2006-1-15 18:07:00 | 显示全部楼层

Re: Re:VC中的delete和delete[]

bombbear: Re:VC中的delete和delete[]

TO [B]hdm2968[/B]:
调用析构函数是没有问题的(注意我的用法),但是能正确释放堆上的内存我只在VC上实验...

不懂........
原因是因为你的是指针?

89

主题

822

帖子

847

积分

高级会员

Rank: 4

积分
847
 楼主| 发表于 2006-1-16 13:01:00 | 显示全部楼层

Re:VC中的delete和delete[]

多出来的指针并不是析购函数指针,大家从我的例子中可以看看
p2同样是有析构函数的,也只有4个字节,只有p1才多出4个字节,有兴趣的可以自己跟踪一下VC,看看这4个字节究竟是干什么呢,哈哈
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-12-20 09:33

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表