导航
  • 全部
...

delete 是否释放被强制转换了的指针指向的空间

stemmer 2009-08-16 07:41:00
如下面这个例子:
char * buffer= new char[1024];
B * b=(B*)buffer;
delete b;
请问:这个空间能否正确释放?谢谢,有什么方法可以验证吗?
...全文
给本帖投票
264 17 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
stemmer 2009-08-16
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 liuchaotao 的回复:]
char * buffer= new char[1024];
B * b=(B*)buffer;
delete b;
显然的不能正确释放.buffer是指向大小为1024的一个堆.而delete b则只释放和习构了类B的空间,除非B的大小刚好等于1024,否则空间释放是不完全的
[/Quote]
我最初的想法和你一样,我刚刚用 pageheap 工具测试了下,如果B是一个简单的stuct,比如struct{int x;},就是说不考虑B的析构的情况下,空间会被全部释放; 也就说delete 的实现是这样的:delete b的实现应该是这样的,获取b的地址,然后向前找到之前new的时候记录下来的信息,据此来释放空间。 12 楼的兄弟说的对
liuchaotao 2009-08-16
  • 打赏
  • 举报
回复
char * buffer= new char[1024];
B * b=(B*)buffer;
delete b;
显然的不能正确释放.buffer是指向大小为1024的一个堆.而delete b则只释放和习构了类B的空间,除非B的大小刚好等于1024,否则空间释放是不完全的
liao05050075 2009-08-16
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 pengzhixi 的回复:]
强制转换成其他类型再释放肯定不安全了.
[/Quote]
呵呵。这个是当然的啊。
比如下面这样程序也就挂了,因为delete b的时候要调用B的析构函数

#include <iostream>
using namespace std;
class B
{
public :
int * a;
B(){a=new int;}
~B(){delete a;}
};

int main ()
{
B * b;
char * buffer= new char[1024*1024];
b=(B*)buffer;
delete b;
return 0;
}
arong1234 2009-08-16
  • 打赏
  • 举报
回复
这样可能会有以下几个问题:
1. 如果B类型重载了operator delete,你的内存可能不被释放,(但是验证这个不容易,因为delete之后,无论它是否被释放你都很难验证)
2. 如果B::~B作了一些操作,有可能造成系统崩溃(如B的析构函数试图释放一个指针,而这个指针不存在,将造成非常严重的问题)

如果你要把一段内存转换为一个类的对象,你需要的是placement new,而不是强制类型转换,对于你的例子,需要这样:

char * buffer= new char[1024];
B * b=new(buffer) B();
delete b;
pengzhixi 2009-08-16
  • 打赏
  • 举报
回复
强制转换成其他类型再释放肯定不安全了.
liao05050075 2009-08-16
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 stemmer 的回复:]
我是这么考虑的。我猜测 delete b 的实现是,获取b的首地址,获取sizeof(B), 据此来释放空间;那么意味着
如果sizeof(B)!=1024 的话,那么就会有内存泄漏; 不知诸位同意否?
[/Quote]

delete b的实现应该是这样的,获取b的地址,然后向前找到之前new的时候记录下来的信息,据此来释放空间。
stemmer 2009-08-16
  • 打赏
  • 举报
回复
我是这么考虑的。我猜测 delete b 的实现是,获取b的首地址,获取sizeof(B), 据此来释放空间;那么意味着
如果sizeof(B)!=1024 的话,那么就会有内存泄漏; 不知诸位同意否?
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 mstlq 的回复:]
引用 6 楼 akirya 的回复:
可以释放,但同时也会调用B的析构函数


请问如果B类的operator delete被重载过的话,这样也安全吗^_^?
[/Quote]
当然不安全,强制转化是错误的根源。
晨星 2009-08-16
  • 打赏
  • 举报
回复
空间应当可以释放(虽然C++语言标准上并没有明确地这么说,但大多数编译器应该可以做到的)。
但析构的调用可能会出问题。
当然,总而言这,最好还是不要这样用。
liao05050075 2009-08-16
  • 打赏
  • 举报
回复
不好意思。1楼的程序中
delete buffer 要改成回delete b,这个是验证之后忘记改回来了
mstlq 2009-08-16
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 akirya 的回复:]
可以释放,但同时也会调用B的析构函数
[/Quote]

请问如果B类的operator delete被重载过的话,这样也安全吗^_^?
  • 打赏
  • 举报
回复
可以释放,但同时也会调用B的析构函数
mstlq 2009-08-16
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 liao05050075 的回复:]
能正确释放。使用下面的程序做验证。
方法:
(1)打开windows任务管理器,然后单步调试程序,注意看当前程序的内存用量变化情况。
(2)注释(1)(3)句,再按上面的方法看内存变化,发现结果是一样的
C/C++ code
#include<stdio.h>struct B
{int a;
};int main ()
{
B* b;//(1)char* buffer=newchar[1024*1024];//(2) b=(B*)buffer;//(3) delete buffer;return0;
}
[/Quote]

楼主好像想detele b而不是delete buffer >_<
deerwin1986 2009-08-16
  • 打赏
  • 举报
回复
肯定可以的 delete的时候才不管是不是分配内存时的那个指针 主要要看内存空间中是否有分配的大小 有就按照那个大小来析构 然后释放。。。
mstlq 2009-08-16
  • 打赏
  • 举报
回复

#include <iostream>
using namespace std;
class B
{
public:
B(){p=new char[9999];}
~B(){cout<<"+_+"<<endl; delete[] p;};
void operator delete(void *){cout<<"+_+ +_+ +_+"<<endl;};
private: char *p;

};
int main()
{
char str[100];
char * buffer= new char[1024];
B * b=(B*)buffer;
delete b;
return 0;
}
liao05050075 2009-08-16
  • 打赏
  • 举报
回复
能正确释放。使用下面的程序做验证。
方法:
(1)打开windows任务管理器,然后单步调试程序,注意看当前程序的内存用量变化情况。
(2)注释(1)(3)句,再按上面的方法看内存变化,发现结果是一样的

#include <stdio.h>

struct B
{
int a;
};

int main ()
{
B * b;//(1)
char * buffer= new char[1024*1024]; //(2)
b=(B*)buffer; //(3)
delete buffer;
return 0;
}

jack_doson 2009-08-16
  • 打赏
  • 举报
回复
delete b;

意思是 b 之前所指向的空间 ,可以被重新放到 堆中,可以重新被申请。。。

而 b 指向了 未知的地址,这时称 b 为 野指针。

最好在 delete b; 之后 给 b = NULL;

上面是我的理解

65,183

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧

手机看
关注公众号

关注公众号

客服 返回
顶部