new/delete与malloc/free的区别

参考:

https://blog.csdn.net/u013485792/article/details/51329541

https://www.cnblogs.com/lyl-312/p/5528892.html

http://www.cnblogs.com/QG-whz/p/5140930.html

https://blog.csdn.net/gukesdo/article/details/7506155

  本文在写作中参考了上述文章,特此感谢!

【导语】

之前对new和delete,malloc和free这两对组合只有个简单的了解,知道必须配合使用来对内存进行控制。近期在工作中用到了malloc和free,结果出现各种内存问题,解决了好久,记录一下当做回顾。

1   C++内存简介

1.1     内存分区

  在C++中内存分为5个区,分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。

  堆:堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序的内存动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。

  栈:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

  自由存储区:自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。(new操作符从自由存储区上为对象动态分配内存空间)

  全局/静态存储区:这块内存是在程序编译的时候就已经分配好的,在程序整个运行期间都存在。例如全局变量,静态变量。

  常量存储区:这是一块比较特殊的存储区,他们里面存放的是常量(const),不允许修改。

1.2     自由存储区

  那么自由存储区是否能够是堆(问题等价于new是否能在堆上动态分配内存),这取决于operator new 的实现细节。自由存储区不仅可以是堆,还可以是静态存储区,这都看operator new在哪里为对象分配内存。

特别的,new甚至可以不为对象分配内存!定位new的功能可以办到这一点:

new (place_address) type

place_address为一个指针,代表一块内存的地址。当使用上面这种仅以一个地址调用new操作符时,new操作符调用特殊的operator new,也就是下面这个版本:

void * operator new (size_t,void *) //不允许重定义这个版本的operator new

这个operator new不分配任何的内存,它只是简单地返回指针实参,然后右new表达式负责在place_address指定的地址进行对象的初始化工作。

所以有的文章简单的将new delete,malloc  free 理解为都是从堆中获取内存。下文中也是以此进行描述,知道基本原理即可。

  另外基于此,有的文章将C++内存的五个区划分为:堆、栈、全局/静态存储区、常量存储区和程序代码区。

  程序代码区:存放程序的二进制代码。

2   new,delete和malloc free的区别

  Ps:关于new和malloc之间的区别请参考下面这篇博客,里面讲解的很详细。

  http://www.cnblogs.com/QG-whz/p/5140930.html

  本文下面从自己的角度简单描述一下。

2.1     构造函数/析构函数

使用new操作符来分配对象内存时会经历三个步骤:

  第一步:调用operator new 函数(对于数组是operator new[])分配一块足够大的,原始的,未命名的内存空间以便存储特定类型的对象。

  第二步:编译器运行相应的构造函数以构造对象,并为其传入初值。

  第三部:对象构造完成后,返回一个指向该对象的指针。

使用delete操作符来释放对象内存时会经历两个步骤:

  第一步:调用对象的析构函数。

  第二步:编译器调用operator delete(或operator delete[])函数释放内存空间。

总之来说,new/delete会调用对象的构造函数/析构函数以完成对象的构造/析构。而malloc则不会,malloc只是简单的分配一块内存给用户使用。

2.2     delete和free的区别

  首先free对应的是malloc;delete对应的是new;free用来释放malloc出来动态内存,delete用来释放new出来的动态内存空间。

  new/delete是C++的操作符,而malloc/free是C中的函数。

应用的区别为:

  1. 数组的时候int *p=(int*)malloc(10*sizeof(int)) 释放的时候 free(p)即可;这是因为编译器对malloc做了一些特殊的处理,以保证可以正确释放内存。

   而当int *p=new int[10]释放的时候应为delete []p,注意[]的作用说明释放的是一个数组的内存,如果delete p则只是释放的p[0],其余9个int的内存没有释放;这是因为当指明为[]的时候,编译器实际上是做了一个循环来释放这个数组的所有内存。

  2. 在类和对象的时候会有很大区别。在使用malloc和free来处理动态内存的时候,仅仅是释放了这个对象所占的内存,而不会调用这个对象的析构函数;使用new和delete就可以既释放对象的内存的同时,调用这个对象的析构函数。

共同之处:

  它们都是只把指针所指向的内存释放掉了,并没有把指针本身干掉。在free和delete之后,都需要把指向清理内存的指针置为空,即p=NULL,否则指针指向的内存空间虽然释放了,但是指针p的值还是记录的那块地址,该地址对应的内存是垃圾,p就成了“野指针”。

  即free和delete之后,是把从堆中获取的内存释放,这部分内存现在可以分配给其它使用。但是栈中的指针本身依然存在,并仍然指向该部分内存。如果不把指针设置为NULL。后面仍然去调用该指针,可以获得这部分内存中的值。但是这部分内存中的值是不确定的,有可能已经被其它程序调用,即“野指针”。如果只是单纯的把指针设置为NULL,没有调用free和delete会导致内存泄露。即从指针判断的话,已经无法访问内存。但是由于没有调用free和delete,导致系统以为这部分内存依然在使用,程序执行过程中无法分配给其它部分,导致内存浪费。

  如果程序较长,我们通常在使用一个指针前会检查p!=NULL,这样就起不到作用了。此时如果再释放p指向的空间,编译器就会报错,因为释放一个已经被释放过的空间是不合法的。而将其置为NULL之后再重复释放就不会产生问题,因为delete一个0指针是安全的。

在这里关于指针和动态申请的内存空间总结如下:

  1. 指针消亡了,并不表示它指示的动态内存会自动释放;

  2. 动态内存释放掉了,如果这个内存是一个动态对象,则并不表示一定会调用这个对象的析构函数;

      动态内存释放掉了,并且调用了析构函数,并不表示指针会消亡或者自动变成了NULL。

new/delete与malloc/free的区别的更多相关文章

  1. C/C++——new/delete和malloc/free的区别

    new/delete和malloc/free的区别 扩容操作: 对于malloc是有一个realloc函数对应用于扩容的: 对于new,只能再new一个,for循环赋值过去,把原来的delete掉: ...

  2. new/delete 和malloc/free 的区别

    new/delete 和malloc/free 的区别 一.基本概念malloc/free:1.函数原型及说明:      void *malloc(long NumBytes):该函数分配了NumB ...

  3. new/delete 与 malloc/free的区别

    一.概述     在C++中,申请动态内存与释放动态内存用new/delete 与 malloc/free都可以,而且他们的存储方式相同,new/malloc申请的动态内存位于堆中,无法被操作系统自动 ...

  4. new/delete和malloc/free的区别

    通俗易懂版本:http://zhidao.baidu.com/question/86185100 1 new/delete和malloc/free最大区别是对对象的理解. 如果你使用 Foo* foo ...

  5. [C/C++] new/delete和malloc/free基本区别

    /**便于遗忘时复习**/ 区别一:本质 new/delete 在C++中是运算符不是函数,需要编译器支持.malloc/free是库函数,需要头文件支持,在C语言中使用. 区别二:开辟内存大小 用 ...

  6. new/delete、malloc/free 的区别

    相同点 1.都可以动态的申请或释放内存 2.存储方式相同,动态申请的内存都存放在堆中,无法自动释放,要调用对应的delete和free   区别 1.new能自行的计算需要分配的空间,malloc需要 ...

  7. C++中,new/delete和malloc/free的区别

    1.new/delete是C++的操作符,而malloc/free是C中的函数. 2.new做两件事,一是分配内存,二是调用类的构造函数:同样,delete会调用类的析构函数和释放内存.而malloc ...

  8. c/c++ 复习基础要点01-const指针、指针函数 函数指针、new/delete与malloc/free区别与联系

    1.      引用本身是有指针实现的:引用为只读指针 例子: int d=123; int& e=d;    //引用 int * const e=d; //只读指针,e指向d,不可修改e指 ...

  9. new/delete和malloc/free区别与联系

    1.基本概念 malloc/free (1).函数原型及说明 void *malloc(long NumBytes): 该函数分配了NumBytes个字节,并返回了指向这块内存的指针.如果分配失败,则 ...

随机推荐

  1. 起步:SpringBoot

    pom.xml <parent> <groupId>org.springframework.boot</groupId> <artifactId>spr ...

  2. jersey实现RESTful接口PUT方法JSON数据传递

    项目中使用的是org.json包 maven中的配置如下: xml <!-- https://mvnrepository.com/artifact/org.json/json --> &l ...

  3. c# 第七节 编程规范,vs中的各种设置

    本节内容: 1:编程规范 2:vs中的各种设置 3:一个解决方案多个项目的创建.使用 1:编程规范 需要规范的地方: 1: 2: 2:vs中的各种设置 实现: 3:一个解决方案多个项目的创建.使用

  4. 201871010126 王亚涛 《面向对象程序设计(Java)》第七周实验总结

    ---恢复内容开始--- 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com ...

  5. Linux用户态与内核态通信的几种方式

    本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. Linux 用 ...

  6. 莫烦TensorFlow_03 Variable加法

    import tensorflow as tf ## 定义变量 state = tf.Variable(0, name = 'counter') #print(state.name) one = tf ...

  7. python 之Entry

    # Tkinter教程之Entry篇 # Entry用来输入单行文本 from tkinter import * root = Tk() # 创建entry Entry(root, text='inp ...

  8. 万字长文把 VSCode 打造成 C++ 开发利器

    https://zhuanlan.zhihu.com/p/96819625 面对大量代码,在开发任务繁重场景下,VSCode 绝对是一把利器.本文虽以 C++为引,但在 python.php.java ...

  9. MyEclipse一直building workspace

    点击Project,点击Bulid Automatically去掉其前面的勾,即取消自动编译工作空间中的所有java文件. 注:不要取消!!!!取消之后如果你修改的java文件和struts.xml等 ...

  10. [LeetCode] 126. Word Ladder II 词语阶梯之二

    Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformat ...