C++ delete 两次
转载自:http://blog.csdn.net/jxluofeng/article/details/19766801
《问题》危险的代码:
int* p=new int(1);
delete p;
delete p;
探讨一:
连续两次对同一个指针delete ,会造成严重的错误。编译器会检测出这样的错误吗?或许一些编译器会的,但别太过指望编译器。
探讨二:
第一次delete后,p自动为空(NULL)了吗?不是的。
探讨三:
在delete之前会自动检查p是否为空(NULL),如果为空(NULL)就不再delete了吗?确实是如此。
探讨四:
删除为空(NULL)的指针是不会有任何问题的吗?确实是如此。
探讨五:
#define SAFE_DELETE(p) delete (p); p = 0;
这样就就万事大吉了吗?好像不是的。
delete p+1;//在C++中是正确的
SAFE_DELETE(p+1)将会导致错误
探讨六:
没有好的方法解决重复释放这样的问题,只能靠程序员的细心了。
《结论》安全的代码:
int* p=new int(1);
delete p;
p = NULL;
(1)delete 一次以后,p成了野指针,它作为地址的值还是有效地没还可以访问它以前指向的内存,不过那片内存被重新格式化了;
(2)p不等于NULL,用 if(p) 语句不能判断它指向的内存是否有效(此时它指向的内存无效,p本身有效);
(3)delete 一次以后,不能再次delete,否则会报错;
(4)此时如果误用p指针,仍然可以修改内存的值和从该处取出数值,但此时数据不受保护,该内存空间可能被重新被分配给别的变量;
(5)如果p指向的空间再次被new函数分配,即使是分配给别的指针,即使分配大小与原来不一样,p又恢复了效力,可以改变内存的值,甚至可以重新被delete,p的作用与新分配的指针一样;
转载自: C++ 一不小心被delete两次
2012-09-11 12:10 by 捣乱小子, 2720 阅读, 31 评论, 收藏, 编辑
2012-09-11 18:04:看到园里朋友们这么热心,有那么一会心里好兴奋。:)
2012-09-11 下午:本文曾出现很严重的错误,但不要紧,感谢园友们的即使指正。
C++类中,有时候使用到传值调用(对象实体做参数),遇到这种情况,可要小心了!特别是当你所传值的对象生命周期较长,而非临时对象(生命周期段)的时候。来看看下面的情况:
#include <iostream>using namespace std;class Text{private: char * str;public: Text(){str = new char[20];::memset(str,0,20);} void SetText(char * str) { strcpy(this->str,str); } char * GetText() const{return str;} ~Text() { cout << "~Text Destruction" << endl; delete [] str; cout << "~Text Over" << endl; }};void Print(Text str){ cout << str.GetText() << endl;}int main(){ Text t; t.SetText("abc"); Print(t); return 1;} |
上面执行的结果程序崩溃了。原因:
Print(Text str)在对str进行复制构造的时候,没有进行深度拷贝;当 Print退出的时候,因为是临时对象(函数初始时构造),对str进行析构,此时还没有任何破绽;但回到main,继而退出main 的时候,又对t进行析构,但此时t内的str中的内容已经被销毁。由于对一内存空间实施了两次销毁,于是出现内存出错。
解决方法:
- 重写浅拷贝。像一下版本,不同的情况要作出适当的调整:
#include <iostream>usingnamespacestd;classText{private:char* str;public:Text(){str =newchar[20];::memset(str,0,20);}Text(Text &t){str =newchar[20];strcpy(str,t.GetText());}voidSetText(char* str){strcpy(this->str,str);}char* GetText()const{returnstr;}~Text(){cout <<"~Text Destruction"<< endl;delete[] str;cout <<"~Text Over"<< endl;}};voidPrint(Text str){cout << str.GetText() << endl;}intmain(){Text t;t.SetText("abc");Print(t);return1;} - (推荐)不使用传值调用。就像下面书写如下Print版本:
voidPrint(Text &str){cout << str.GetText() << endl;} - 评论中的小伙伴还提供了一个方法,很值得推荐,同时这也是编程良好的习惯:指针在使用的时候需要作空判断,在删除指针时候需要置空。
后记——语言的探讨
C++,以至于其他的程序语言,都是伟大的创造。他们是规则的世界,一愣一脚皆规则。当对某一规则有所熟知之后,就似发现新大陆似的。但想想,这些规则可经不起碰撞打击,殃及的是coder,是我们。这些规则不像1+1=2,“三点定面”来的铁定,总之比起数学理论来说,似乎程序规则脆弱很多,总之在它们身上看到的价值是有限的,总我还是选择了计算机...为之奈何,不得而知。
C++ delete 两次的更多相关文章
- 小心指针被delete两次
C++类中,有时候使用到传值调用(对象实体做参数),遇到这种情况,可要小心了!特别是当你所传值的对象生命周期较长,而非临时对象(生命周期段)的时候.来看看下面的情况: #include <ios ...
- mysql delete两种关联删除方式
基本格式: DELETE t1 FROM t1,t2 WHERE t1.id=t2.id 或 DELETE FROM t1 USING t1,t2 WHERE t1.id=t2.id 示例应用: ...
- 内存管理运算符new delete与内存管理函数malloc free的区别——已经他们对对象创建的过程。
(1)内存管理函数与内存管理运算符的区别 内存管理函数有内存分配函数,malloc calloc realloc 以及内存释放函数free. 内存管理运算符有new 和delete. 两种内存管理方式 ...
- delete和delete[]
c++中对new申请的内存的释放方式有delete和delete[两种方式,到底这两者有什么区别呢? 1.我们通常从教科书上看到这样的说明:delete 释放new分配的单个对象指针指向的内存dele ...
- 为什么使用enable_shared_from_this——shared_ptr两类错误
在使用C++实现弱回调时,订阅者应当维护一系列发布者的weak_ptr,而发布者注册回调时要传出this的shared_ptr指针,流行的实现方法是使用std::enable_shared_from_ ...
- delete 和 delete [] 的真正区别
c++中对new申请的内存的释放方式有delete和delete[两种方式,到底这两者有什么区别呢? 1.我们通常从教科书上看到这样的说明: delete 释放new分配的单个对象指针指向的内存 de ...
- 关于delete和delete[]的区别
在C++动态内存分配中我们常用到new和delete两种操作,new用来申请内存,delete用来释放内存.那么问题来了,我们应该用delete来释放内存还是用delete[]来释放内存呢? 为了得到 ...
- 转 delete 和 delete []的真正区别
c++中对new申请的内存的释放方式有delete和delete[两种方式,到底这两者有什么区别呢? 1.我们通常从教科书上看到这样的说明:delete 释放new分配的单个对象指针指向的内存dele ...
- delete释放空间时出错的原因
int *a=new int[10]; ...... delete []a; 后面“delete []a;”出现错误的情况大致有: 1 数组的首地址a被你有意无意更改了,如:a++之类的: 2 变量的 ...
随机推荐
- linux-shell——01
没有什么好的标题,只是一些随笔.我用的是linux虚拟机,red hat 7 一:nat模式使得虚拟机可以访问外网,但是这种模式下只可以访问外网,但外面的不能访问里面 首先将虚拟机的网络连接改为nat ...
- 栈--数据结构与算法Javascript描述(4)
栈 Stack 概念 栈是一种高效的数据结构,数据只能在栈顶添加或者删除,所以这样的操作很快,而且容易实现.栈的使用遍布程序语言的方方面面,从表达式求值到处理函数调用. 栈是一种特殊的列表,栈内的元素 ...
- 十一、mysql老是停止运行该怎么解决
mysql老是停止运行该怎么解决 你可能还会遇到无法启动mysql的错误 解决方法如下:
- 9.1 mysql+centos7+主从复制
MYSQL(mariadb) MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可.开发这个分支的原因之一是:甲骨文公司收购了MySQL后,有将MySQL闭源的 ...
- android IPC 进程间通讯
参考资料: http://blog.csdn.net/birdsaction/article/details/39451849 在这里我说一下学习技术的方法,别人的博客,别人的东西,再简单,自己没有写 ...
- 《Cracking the Coding Interview》——第8章:面向对象设计——题目9
2014-04-23 23:57 题目:如何设计一个内存文件系统,如果可以的话,附上一些代码示例. 解法:很遗憾,对我来说不可以.完全没有相关经验,所以实在无从入手.这题目应该和工作经验相关吧? 代码 ...
- win7 64位如何共享XP上的打印机?
这个问题看似很简单,但是一旦你遇到了,就会发觉不是想象的那么简单. 除了网上能搜到的一些设置之外,这里还有几个诀窍: 1.首先你必须准备你的打印机的64位驱动程序 2.你在win7上必须采用添加本地打 ...
- Java中Set的contains()方法——hashCode与equals方法的约定及重写原则
转自:http://blog.csdn.net/renfufei/article/details/14163329 翻译人员: 铁锚 翻译时间: 2013年11月5日 原文链接: Java hashC ...
- 获取访问者ip及其所在城市
原本使用新浪Api,然后发现不行了,以下小编重新查找了几个,个人推荐太平洋的接口 1.首先获取真实ip $ip = $_SERVER['REMOTE_ADDR']; 2.要知道的Api接口 几个接口$ ...
- C编译器MinGW安装、下载及在notepad++中运行C程序
一.C编译器MinGW的下载及安装步骤 打开MinGW官网:http://www.mingw.org/ 图一 图二 图三 图四 图五 图六 系统中配置环境变量: 图七 验证是否安装成功: CMD中运行 ...