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>
using
namespace
std;
class
Text
{
private
:
char
* str;
public
:
Text(){str =
new
char
[20];::
memset
(str,0,20);}
Text(Text &t)
{
str =
new
char
[20];
strcpy
(str,t.GetText());
}
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版本:
void
Print(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 变量的 ...
随机推荐
- Django+vue在腾讯云上搭建前后端分离项目
最近打算用Django+vue搭建一个个人主站,在此记录一下搭建项目的整个过程. 一 开发环境: 腾讯云Centos 7 Python 3.7 Django ...
- 用python实现【五猴分桃】问题
转载链接:https://blog.csdn.net/cy309173854/article/details/78296839 据说“五猴分桃”问题最先是由大物理学家狄拉克提出来的,这一貌似简单的问题 ...
- python基础之数据类型与变量patr1
1:编写for循环,利用索引遍历出每一个字符 msg='hello egon 666' 2:编写while循环,利用索引遍历出每一个字符 msg='hello egon 666' 3:msg='hel ...
- 集合源码分析之 HashSet
一 知识准备 HashSet 是Set接口的实现类,Set存在的最大意义区别于List就是,Set中存放的元素不能够重复,就是不能够有两个相同的元素存放在Set中,那么怎样的两个元素才算是相同的,这里 ...
- 查询数据库里当前用户下的所有表的总共数据sql
select t.table_name,t.num_rows from user_tables t select sum(num_rows) from user_tables t
- VSX-2 搭建项目
由于是公司的项目,也不可能直接拿过来写博客,所以准备搭建一个自己的VSX项目. 项目需求这里就不写了,大体可参考曾经的一篇文章,这个VSX项目就是用来简化插件式开发. 本文开始正式记录做这个VSX项目 ...
- ITIBB原创,互联网首部自媒体小说《1024伐木累》-小白篇之入职-总章节一
小序 IT人不懂爱?代码汪是小白?又有谁,懂我情怀? 逗比青年,背上行囊,懵懵懂懂闯帝都!前途似海,来日方长! 青春无梦妄少年!认定就作,不平就说,碰撞火花,如此绚烂…… IT人有比格?其实,那是顽强 ...
- SSH集成cxf 发布restful webservice
首先讲一下什么是restful webservice ,这个问题网上一搜有很多博文去长篇大论的介绍它,但是最后你看完了也会觉得云里雾里的,所以我在这里简单的讲一下我理解的rest webservice ...
- 一个初学者的辛酸路程-继续Django
问题1:HTTP请求过来会先到Django的那个地方? 先到urls.py ,里面写的是对应关系,1个URL对应1个函数名. 如果发URL请求过来,到达这里,然后帮你去执行指定的函数,函数要做哪些事 ...
- 数据库——pymysql模块的使用(13)
1.基本用法——建立链接,获取游标,执行sql语句,关闭 建立远程链接账号和权限 mysql> grant all on *.* to '; Query OK, rows affected, w ...