delete指针以后应赋值为NULL
delete p后,只是释放了指针中存放的地址中的内存空间。但是指针变量p仍然存在(即指针p本身所占有的内存),且p中存放的地址还是原来的地址。
例如:
对一个非空指针delete后,若没有将p赋为NULL,若再次delete的话,会出现问题。
如下代码:
#include <iostream>
int main()
{
int* p = new int();
delete p;
delete p;
return ;
}
在ubuntu14.04中使用g++进行编译无问题,但运行时报错如下:

意思就是对同一指针变量进行了两次释放内存的操作,这是不合法的。
因为第一次释放后,指针p指向的那块区域已经变为不可访问区域了,再执行一次delete p,试图对一块不可访问的区域进行释放,这是不合法的。
将其改为:
#include <iostream>
int main()
{
int* p = new int();
delete p;
p = NULL;
delete p;
return ;
}
则编译和运行都没有问题,因为C++保证delete值为NULL的指针是安全的。
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
具体的说明如下:
还是先看代码:
/*
*Compile Environment:linux ubuntu14.04.5 g++
*Author: mengjia
*Date:20180520
**/
#include <iostream>
using namespace std;
int main()
{
int *p = new int;
*p = ;
cout << "将3赋给p的地址后,指针p读取的值:" << *p << endl;
cout << "删除空间前,指针p中存放的地址:" << p <<endl;
delete p;
cout<<"删除空间后,指针p存放的地址:"<< p <<endl; //在vs2017中,p中存放的地址会改变,但在g++中不会,应该是vs2017中对其进行优化了,让p指向了一个不可访问的地址,避免delete之后又误操作了p
cout << "删除空间后,指针p读取的值:" << *p << endl; //在vs2017中,对×p的访问直接会报错(引发了异常: 读取访问权限冲突),但在g++中,可
以正常往下执行。
long *p1 = new long;
*p1 = ;
cout << "创建新空间后,指针p中存放的地址:" << p << endl;
cout << "指向新空间的指针p1存放的地址:" << p1 << endl;
*p = ;
cout << "将23赋给p的地址后,指针p读取的值:" << *p << endl;
cout << "将23赋给p的地址后,指针p1读取的值:" << *p1 << endl;
delete p1;
// system("pause");
return ;
}
输出结果为:

从第13和第15行中可以看到,delete指针p前后,p中存放中地址并未改变。这就说明一个非常重要的结论:
delete一个指针后,编译器只是释放了指针中存放的地址中的内存空间,但p中存放的地址还是原来的地址。
在程序的第18行,创建了一个long型的指针p1,在20和21行的输出中发现,指针p保存的地址居然和指针p1保存的地址一毛一样。说明指针p和指针p1都指向内存的同一个地方。出现这种状态是因为编译器默认将释放掉的内存空间回收然后分配给新开辟的空间。所以行,当开辟一个可以保存long型变量的空间并且由p1来指向它时,分配的空间为p指向的内存空间。
如此,将导致两个指针同时指向同一内存空间。这在C++中是非常忌讳的。
如上,在程序中定义了*p1 = 100;而后再操作p,使*p = 23;而后读取p1指向的内存中的值,变为了23。这就会使得已经delete的指针,若操作不当,会影响到程序的其它指针。这种情况就是由于野指针p造成的。
要避免这种情况的发生,解决办法就是:
在删除一个指针之后,一定要将该指针设置成空指针,即在delete p之后,要加上: p = NULL
补充说明:
请注意程序中第15行和16行的注释,这段程序在vs2017上是编译不通过的。原因就如注释所言,vs2017对其进行了优化,delete之后,让p的指向改变了,改变为指向一个不可访问的地址,使得之后如果有任何*p相关的操作,都会直接报错。其目的,我觉得就是保证在源头断绝,不让出现野指针的情况。
但这种依赖于编译器的优化,对我们理解C++并没有好处。
delete指针以后应赋值为NULL的更多相关文章
- delete指针以后应赋值为NULL——QT deletelater指针以后也同样要马上赋值为NULL
delete p后,只是释放了指针指向的内存空间.p并不会自动被置为NULL,而且指针还在,同时还指向了之前的地址 delete NULL编译器不会报错(因为delete空指针是合法的) 例: 对一个 ...
- C++在delete指针后要赋值为NULL
C++标准规定:delete空指针是合法的,没有副作用. 所以我们在Delete指针后赋值为NULL或0是个好习惯.对一个非空指针delete后,若没有赋NULL,若再次delete的话 有可能出现问 ...
- [转载]delete指针之后应该赋值NULL
首先,C++标准规定:delete空指针是合法的,没有副作用.但是,delete p后,只是释放了指针指向的内存空间.p并不会自动被置为NULL,而且指针还在,同时还指向了之前的地址. 问题来了,对一 ...
- 指针delete之后赋值为null
1.现象 经常看到有些代码在delete之后赋值为null 2.原因 C++标准规定:delete空指针是合法的,没有副作用. 所以我们在Delete指针后赋值为NULL或0是个好习惯.对一个非空指针 ...
- C语言_指针变量的赋值与运算,很详细
指针变量的赋值 指针变量同普通变量一样,使用之前不仅要定义说明, 而且必须赋予具体的值.未经赋值的指针变量不能使用, 否则将造成系统混乱,甚至死机.指针变量的赋值只能赋予地址, 决不能赋予任何其它数据 ...
- C++ 指针悬挂和赋值操作符的重载,拷贝构造函数实现
指针悬挂: 问题:使用new申请的内存内存空间无法访问,也无法释放. 原因:直接对指向new申请的存储空间的指针变量进行赋值修改 后果:失去了原来的地址,原来的空间无法访问也无法释放,造成内存泄漏 还 ...
- 【Java讨论】引用类型赋值为null对加速垃圾回收的作用(转载)
:有一些人认为等于null可以帮助垃圾回收机制早点发现并标识对象是垃圾.其他人则认为这没有任何帮助.是否赋值为null的问题首先在方法的内部被人提起.现在,为了更好的阐述提出的问题,我们来撰写一个Wi ...
- delete 指针
#include<iostream>using namespace std;class human{public: human(){cout<<"构造";} ...
- [No000017C]改善C#程序的建议5:引用类型赋值为null与加速垃圾回收
在标准的Dispose模式中(见前一篇博客“C#中标准Dispose模式的实现”),提到了需要及时释放资源,却并没有进一步细说让引用等于null是否有必要. 有一些人认为等于null可以帮助垃圾回收机 ...
随机推荐
- netty的HelloWorld演示
pom <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artif ...
- python 模块二(os,json,pickle)
#################################总结##################### os常用 os.makedirs('baby/安哥拉/特斯拉/黄晓明') os.mkd ...
- redis注册成window服务 标签: redis
注册服务 redis-server.exe –service-install redis.windows.conf 删除服务 redis-server –service-uninstall 开启服务 ...
- Android开发入门经典实例
开发实例概述 今天带大家做一个简单的Android App,这个App会显示创新工程实践老师们的照片和信息,不妨先看一看效果: 虽然这个App非常简单,但是涉及到了Android开发中的一些关键知识, ...
- try{s.send(t.hasContent&&t.data||null)}catch(e){if(n)throw e}}引发的惨案
如题,ajax请求报错:try{s.send(t.hasContent&&t.data||null)}catch(e){if(n)throw e}}引发的惨案 要么是404,要么是40 ...
- [leetcode-120] 三角形最小路径和
三角形最小路径和 (1过) 给定一个三角形,找出自顶向下的最小路径和.每一步只能移动到下一行中相邻的结点上. 例如,给定三角形: [ [2], [3,4], [6,5,7], [4,1,8,3] ] ...
- parseDouble()方法
String a = "269"; double parseDouble = Double.parseDouble(b); System.out.println(“Double a ...
- luogu P3726 [AH2017/HNOI2017]抛硬币
传送门 我是真的弱,看题解都写了半天,,, 这题答案应该是\(\sum_{i=1}^{a}\binom{a}{i}\sum_{j=0}^{min(b,i-1)}\binom{b}{j}\) 上面那个式 ...
- 第27月第12天 webrtc ios openssl boost
1. source 'https://github.com/CocoaPods/Specs.git' target 'YOUR_APPLICATION_TARGET_NAME_HERE' do pla ...
- NIO的epoll空轮询bug
JDK NIO的bug,例如epoll bug,它会导致Selector空轮询,最终导致CPU 100%. Selector BUG出现的原因 若Selector的轮询结果为空,也没有wakeup或新 ...