C++指针delete后还要置为null
非常好的一篇说明:
转载:https://blog.csdn.net/qq_36570733/article/details/80043321
众所周知,最开始我们用new来创建一个指针,那么等我们用完它之后,一定要用delete将该指针删掉。但是,值得注意的是,难道就仅仅是删除这个指针这么简单的么?下面,我们用一个程序来说明这个问题:
- #include <iostream>
- using namespace std;
- int main()
- {
- int *p=new int;
- *p=3;
- cout<<"将3赋给p的地址后,指针p读取的值:"<<*p<<endl;
- delete p;
- cout<<"删除空间后,指针p读取的值:"<<*p<<endl;
- long *p1=new long;
- *p1=100;
- cout<<"创建新空间后,指针p中保存的地址:"<<p<<endl;
- cout<<"指向新空间的指针p1保存的地址:"<<p1<<endl;
- *p=23;
- cout<<"将23赋给p的地址后,指针p读取的值:"<<*p<<endl;
- cout<<"将23赋给p的地址后,指针p1读取的值:"<<*p1<<endl;
- delete p1;
- return 0;
- }
在上面这个程序中,我们在第8行就将指针p利用delete删掉了。但是,我们来看看程序的输出结果:
对照着上面的程序,我们来分析一下这个输出。首先,我们在程序的第5行初始化了一个指针p。之后输出指针p读取的值。由于第6行的原因,程序肯定会输出3了。之后,我们在程序的第8行删除了这个指针p。但是我们惊奇的发现,在程序的第9行竟然可以输出指针p读取的值。我们不是已经把它删了么?其实不然,debug,上图:
从监视窗口中,我们可以看见虽然程序的第8行已经将指针p删除了,但是在监视窗口中p仍然存在,只是*p所指向的值不再是原来的3了,而是一个随机数。这里就说明了一个非常重要的概念:我们在删除一个指针之后,编译器只会释放该指针所指向的内存空间,而不会删除这个指针本身。
然后我们接着往下分析。在程序的第10行我们又创建了一个long型的指针p1。在12行与13行的输出中我们惊奇地发现,指针p保存的地址居然和指针p1保存的地址一模一样!这个就说明了指针p和指针p1都指向内存的同一个地方!!!出现这种状况的原因其实是由于编译器。编译器默认将释放掉的内存空间回收然后分配给新开辟的空间。所以在第11行由于我们新开辟了一个可以保存long型变量的空间并且由p1来指向它,那么这里的p1指向的其实就是在程序第8行释放掉的内存空间,即p指向的内存空间!所以,这就导致了两个指针同时指向同一个内存空间。这是多不安全的一件事情啊!要知道,我们是把指针p删了的啊!如果再重新对*p进行赋值操作,那么不是会连着*p1一起改动么?
果然,让我们担心的事情出现了。我们明明在程序的第11行中定义了*p1的值为100,但是在输出上面,指针p1读取的值竟然也是23。这个原因就是因为野指针p造成的。我们可以看到,在程序的第14行我们将23赋给了*p。又由于p和p1指向的是同一块内存单元,所以在这里相当于也将p1所指向的内存单元中的值(原来是100),改成了23!这样必然会导致程序的出错!
那么我们就不禁要问了,对于这种由于野指针造成的问题,有没有解决的方法呢?答案当然是有的了。我们只需要牢记下面这句话:
在删除一个指针之后,一定将该指针设置成空指针(即在delete *p之后一定要加上: p=NULL)
我们来看一下在stdio.h中关于关键字NULL的定义:
- /* Define NULL pointer value */
- #ifndef NULL
- #ifdef __cplusplus
- #define NULL 0
- #else
- #define NULL ((void *)0)
- #endif
- #endif
注意上面定义的第5行。这里其实就说明了NULL就是0。也就是说,我们在删除完指针p之后,一定要把它变成空指针!只有这样,才会杜绝上面程序中出现的野指针的错误。
p.s. 对于NULL的应用,我们不应该仅限于上面的方法,还可以应用NULL来判断指针是否初始化成功了,如下例if中的判断方法:
- #include <iostream>
- using namespace std;
- int main()
- {
- int *p=new int;
- if (p==NULL)
- {
- //判断指针p是不是空指针,如果是空指针,那么程序在这里就应该报错
- //报错的方法有很多,比如说返回一个ERROR值:
- //return ERROR;
- }
- //判断了操作成功之后我们才能进行一系列的操作
- //...
- //用完指针p之后,一定要将其删掉。这样可以杜绝野指针的存在
- delete p;
- //删除指针p之后,一定要加上下面这句话,免得成为野指针
- p=NULL;
- }
好了,下次一定要记住,在分配空间给指针之后,一定要用NULL来判断一下是否成功了。然后在删除这个指针的时候,也要用NULL来赋给指针,杜绝成为野指针!
C++指针delete后还要置为null的更多相关文章
- 转载:指针delete后要设置为NULL
本文来自:http://rpy000.blog.163.com/blog/static/196109536201292615547939/ 众所周知,最开始我们用new来创建一个指针,那么等我们用完它 ...
- C++在delete指针后要赋值为NULL
C++标准规定:delete空指针是合法的,没有副作用. 所以我们在Delete指针后赋值为NULL或0是个好习惯.对一个非空指针delete后,若没有赋NULL,若再次delete的话 有可能出现问 ...
- free 或delete后指针怎么样了
free()和delete()只是把指针所指向的内存释放掉,但是并没有把指针本身删除,也没有把指针置为NULL; #include<iostream> using namespace st ...
- C语言关闭日志文件时忘了将日志文件全局变量指针置为NULL
C语言写了一个write_log函数以写日志,写了一个close_log_file函数以关闭日志,声明了一个日志文件全局变量文件指针plogFile. write_log中首先判断plogFile是否 ...
- 指针delete之后赋值为null
1.现象 经常看到有些代码在delete之后赋值为null 2.原因 C++标准规定:delete空指针是合法的,没有副作用. 所以我们在Delete指针后赋值为NULL或0是个好习惯.对一个非空指针 ...
- C++ delete后的指针在不同编译器下的状态差异
今天看到小伙伴分享的一个问题,小伙伴用的MSVC2019编译器,在对delete后的指针进行取值操作时触发了访问冲突. #include<iostream> using namespace ...
- free之后将指针置为NULL
free一个指针,只是将指针指向的内存空间释放掉了,并没有将指针置为NULL,指针仍指向被释放掉的内存的地址,在判断指针是否为NULL的时候,通常是通过if(pt == NULL) ,这时,导致指针成 ...
- sql server 测试delete后数据空间情况
总结结论: [1]如果是索引组织表,删除的数据空间是会被文件设置为可用状态,其他表都可以使用. [2]如果是堆表,删除数据空间也会设置为可用状态,但是只能给被删除数据的表使用. [3]truncate ...
- JavaScript学习笔记-元素在滚动条滑动一定高度后自动置顶
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...
随机推荐
- springBoot整合spring security实现权限管理(单体应用版)--筑基初期
写在前面 在前面的学习当中,我们对spring security有了一个小小的认识,接下来我们整合目前的主流框架springBoot,实现权限的管理. 在这之前,假定你已经了解了基于资源的权限管理模型 ...
- Blazor带我重玩前端(六)
本文主要讨论Blazor事件内容,由于blazor事件部分很多,所以会分成上下两篇,本文为第二篇. 双向绑定 概述 如图所示 当点击单项绑定的时候,MyOnewayComponent里的属性值会发生变 ...
- java工具类去掉字符串String中的.点。android开发java程序员常用工具类
下面是工具类详细代码: package com.qq986945193.david; /** * qq986945193 Project * ============================= ...
- C# Chart各个属性详细解析、应用
Chart笔记 前台页面代码: <form id="form1" runat="server"> <div> <asp:Chart ...
- 分布式事务和分布式hash
分布式事务是什么? 分布式事务就是保证各个微服务之间数据一致,本质上就是保证不同数据库的数据一致性.一致性状态包含 强一致性,任何时刻,所有节点中数据都是一样的 弱一致性,数据更新后,只能访问到部分节 ...
- Codeforces 1337D Xenia and Colorful Gems
题意 给你3个数组\(a, b\)和\(c\),最小化\((x-y)^2+(y-z)^2+(z-x)^2\),其中\(x \in a, y \in b, z \in c\). 解题思路 这题其实第一眼 ...
- Oracle WITH 语句 语法
With语句可以在查询中做成一个临时表/View,用意是在接下来的SQL中重用,而不需再写一遍. With Clause方法的优点: 增加了SQL的易读性,如果构造了多个子查询,结构会更清晰. 示例: ...
- Java 序列化界新贵 kryo 和熟悉的“老大哥”,就是 PowerJob 的序列化方案
本文适合有 Java 基础知识的人群 作者:HelloGitHub-Salieri HelloGitHub 推出的<讲解开源项目>系列. 项目地址: https://github.com/ ...
- pycharm写的代码提交到git上,提示需要merge失败时解决办法
当遇到pycharm代码提交需要合并报错时 原因:pycharm目录和git中目录冲突了 解决办法:1.先在git仓库中创建一个文件夹,比如day1 2.然后在pycharm中update一下,可以看 ...
- Linux实战(16):Centos history命令进阶
因在使用history命令是发现历史命令不同步,没有时间戳,在查看历史操作的时候很不方便,特查询了相关文档,发现可通过系统自带的logger来记录跟踪,历史命令执行的用户,时间,登录IP. vim / ...