delete p后,只是释放了指针指向的内存空间。p并不会自动被置为NULL,而且指针还在,同时还指向了之前的地址

delete NULL编译器不会报错(因为delete空指针是合法的)

例:

对一个非空指针delete后,若没有赋NULL,若再次delete的话,有可能出现问题。

如下代码

int *p = new int(3);

delete p;

delete p;

用VC编译运行将出现问题。

将其改为:

int *p = new int(3);

delete p;

p = NULL;

delete p;

则不会出现问题(因为delete空指针是合法的)。

转自:http://blog.csdn.net/hudfang/article/details/43054243

具体的详细原因看下面的例子:

《delete一个指针之后,要记得设置为NULL  》

众所周知,最开始我们用new来创建一个指针,那么等我们用完它之后,一定要用delete将该指针删掉。但是,值得注意的是,难道就仅仅是删除这个指针这么简单的么?下面,我们用一个程序来说明这个问题:

 #include <iostream>
using namespace std;
int main()
{
int *p=new int;
*p=;
cout<<"将3赋给p的地址后,指针p读取的值:"<<*p<<endl;
delete p;
cout<<"删除空间后,指针p读取的值:"<<*p<<endl;
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;
return ;
}

在上面这个程序中,我们在第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来赋给指针,杜绝成为野指针!

O(∩_∩)O哈哈~写完,收工~~~~

转自:http://www.cnblogs.com/uniqueliu/archive/2011/07/18/2109778.html#

《对指针调用deletelater()后能立即将指针赋值为0吗》

http://bbs.csdn.net/topics/390091038

比如我有一个对象A,含有一个指向某个对象(例如QUdpSocket)的指针,该对象A通过movetothread移动了一个次线程,然后在次线程中new了一个QUdpSocket对象,并把地址赋值给了对象A的那个指针,这样QUdpSocket对象也是在次线程中了。
我的问题是,我需要在次线程析构前删除掉对象A,因此需要给A写一个析构函数。在函数体里对指向socket的指针调用deletalater(),这样在回到次线程的时间循环后就能安全的删除指针所指对象了。但是我能在调用完deleterlater后直接将
指针赋值为null吗,也即:

if(m_udpsocket)
{
m_udpsocket->deletaLater();
m_udpsocket = ;
}

文档中说deleterLater并不是立即被调用,而是把这个删除时间加入到一个事件循环里了。所以,我想如果按照上面的代码所写,会不会出现这种情况:当删除事件加入循环队列后,指针被赋值为0,接着删除事件被处理,这时因为指针为0,所以堆对象删除失败,造成了内存泄露?我自己在下面试了下,没有碰见这种情况,但还是觉得不妥,不应该在后面对指针赋值为0.但是不这样做的话,那这个指针岂不就成了一个野指针。在别的情况,我可能还想多次重复利用这个指针,那这样不就用不了了吗?

答:当然可以,deleteLater并不依赖于这个指针的值,只能使用直接调用函数的方式,

  不能使用connect(p***, SIGNAL(disconnected()), p***, SLOT(deleteLater()));

connect(p***, SIGNAL(disconnected()), this, SLOT(sltClose()));

       void sltClose()

       {

          p***=NULL;//槽函数调用没有固定顺序

        }

看http://www.cnblogs.com/liushui-sky/p/5851936.html中

注:我理解调用deletelater (如指针QTcpSocket *p调用 p->deletelater();)之后已经把当前的QTcpSocket 对象的内存地址通过this赋值给消息队列了,所以把外部的指针p置为NULL不影响最终对象的delete。

记住:p存放的是指向QTcpSocket对象的内存地址,而p本身只是一个指针地址。

参考:http://blog.csdn.net/zzwdkxx/article/details/50748908

delete指针以后应赋值为NULL——QT deletelater指针以后也同样要马上赋值为NULL的更多相关文章

  1. Qt 智能指针学习(7种指针)

    Qt 智能指针学习 转载自:http://blog.csdn.net/dbzhang800/article/details/6403285 从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ ...

  2. 关于空指针NULL、野指针、通用指针 (转)

    reference:https://www.cnblogs.com/losesea/archive/2012/11/16/2772590.html 首先说一下什么是指针,只要明白了指针的含义,你就明白 ...

  3. 关于空指针NULL、野指针、通用指针

    http://www.cnblogs.com/losesea/archive/2012/11/16/2772590.html 首先说一下什么是指针,只要明白了指针的含义,你就明白null的含义了.假设 ...

  4. 值为NULL的对象指针

    相信大家对NULL不会很陌生,NULL 是一个标准规定的宏定义,用来表示空指针常量,当一个指针变量被赋值为NULL时,表示它不再指向任何有效地址,无法在访问任何数据.在VS2012库文件stdio.h ...

  5. 黑马程序员-nil Nil NULL NSNull 野指针和空指针

    空指针1.空指针指不含有任何内存地址的指针.在没有具体初始化之前,其被符值为0Dog * dog = nil;Dog * dog = NULL;都为空指针2.野指针指指向的内存为垃圾内存,导致其值不确 ...

  6. 实体类相同属性间赋值与如何判断实体类中是否所有的字段都为null

    1,实体类相同属性间赋值 /// <summary> /// 将实体2的值动态赋值给实体1(名称一样的属性进行赋值) /// </summary> /// <param ...

  7. Qt deletelater函数分析(1)

               生活的全部意义在于无穷地探索尚未知道的东西,在于不断地增加更多的知识.--左拉 该函数是QObject类的函数:                             ---- ...

  8. c++继承构造子类调用父类构造函数的问题及关于容器指针的问题及当容器里储存指针时,记得要手动释放

    看下面的一个问题: class Person { private: string name; public: Person(const string& s=""){ nam ...

  9. ES6中的变量的解构赋值, 解放我们的双手,实现变量的批量赋值

    ES6--变量的解构赋值 引言 正文 一.数组的解构赋值 解构失败 不完全解构 默认值 二.对象的解构赋值 三.字符串的解构赋值 结束语 引言 变量的解构赋值, 听起来很复杂, 简单点说可以理解成批量 ...

随机推荐

  1. json字符串序列化exception处理

    一.背景: 使用REST接口接收远端传送过来的Json格式String,需要把这个String序列化成响应的对象. 二.问题: 对方封装了一个错误的json格式过来,程序就挂了…… 三.似乎解决: 通 ...

  2. mysql 查看是否被锁

    SHOW OPEN TABLES FROM huahua

  3. laravel的模型和数据库基础操作

    laravel分为三大数据库操作(DB facade[原始查找],查询构造器[Query Builder],Eloquent ORM): use Illuminate\Support\Facades\ ...

  4. cocos2dx当节点存在缩放时要注意的问题

    cocos2dx(所有引擎也均如此),如果一个节点存在缩放,一定不要忘了其局部空间里的单位长度也会发生变化.其子节点位移,局部空间转世界空间结果等都会受影响. 有时候我们想将父节点的缩放转移到子节点中 ...

  5. linux分享一:进程全攻略--守护进程(服务)

    概括: 进程是程序的运行实例.进程对应一个唯一的进程PID, 统一程序的多个实例可以同时运行,他们的pid互不相同. 进程一般分为交互进程.批处理进程和守护进程(daemons)三类 一:什么是守护进 ...

  6. springcloud Ribbon自定义负载均衡插件

    现在我们通过插件的方式添加新的一种策略. package com.zhuyang.config; import org.springframework.beans.factory.annotation ...

  7. Common Probability Distributions

    Common Probability Distributions Probability Distribution A probability distribution describes the p ...

  8. ISE联合modelsim功能仿真和综合后仿真1

    1.代码输入 (1).新建一个ISE工程,名字为count4. (2).新建一个verilog文件 (3).选择verilog module 输入file name为count4,单击next默认知道 ...

  9. vim学习日志(5):vim下wimrc的配置,解决中文乱码问题

    解决linux下vim乱码的情况:(修改vimrc的内容) 全局的情况下:即所有用户都能用这个配置 文件地址:/etc/vimrc 在文件中添加: ,ucs-bom,gb18030,gbk,gb231 ...

  10. Linux shell 执行修改配置文件中的内容

    在开发的过程中可能Linux环境不一致需要适应本地环境的HOME目录,可以通过脚本来修改配置文件内容,写一个test.sh的脚本 在脚本里写入以下命令 sed -i “s#ftfts_com_serv ...