C++基础之 new/delete 概述

目录:

1. 开辟一个元素的空间

2. 开辟一个数组的空间
例1

常考题1:new/delete表达式与malloc/free的区别是?

常考题2:malloc的底层实现?free如何回收内存?

常考题3:什么是内存泄漏,内存溢出,内存踩踏,野指针?




开辟内存方法 new/delete


在C中用来开辟和回收堆空间的方式是采用malloc/free库函数,在C++中提供了新的开辟和回收堆空间的方式,即采用 new/delete 表达式。

C malloc/free函数:1. 申请空间 — 2. 初始化 — 3. 赋值 — 4. 释放堆空间

C++ new/delete 表达式:1. 申请空间,初始化并赋值 — 2. 释放堆空间



1. 开辟一个元素的空间

int * p = new int(1); //申请堆空间并赋值
cout << *p << endl; 
delete p;



2. 开辟一个数组的空间

用new分配对象数组,要在类型名后根一对方括号,在其中指明要分配对象的数目(可以是整型,可以不是常量)

初始化

int * p = new int[10]; // 10 个未初始化的 int
int * p = new int[10](); // 10 个初始化为 0 的 int

我们就可以开辟一个数组的空间

int * p = new int[10]();//开辟数组时,要记得采用[] 
for(int idx = 0; idx != 10; ++idx) 
{    
	p[idx] = idx; 
} 
delete []p;//回收时,也要采用[]

例:

#include <iostream>

using std::cout;
using std::endl;

void newFunc()
{
    int * p = new int(1);
    cout << "*p is " << *p << endl;
    delete p;

    int * p2 = new int[10]();
    for(int i = 0; i != 10; ++i)
    {
        p2[i] = i;
        cout << "p2[i] = " << i <<", ";
    }
    cout << endl;
    delete []p2;
}


int main()
{
    newFunc();
    return 0;
}



常考题1:new/delete表达式与malloc/free的区别是?

区别:

  1. malloc/free 是C/C++语言的标准库函数,new/delete 是C++的运算符或表达式 ;

  2. new 能够自动分配空间大小,malloc需要传入参数;

  3. new 开辟空间的同时还对空间做了初始化的操作,而 malloc 不行;

  4. new/delete 能对对象进行构造和析构函数的调用,进而对内存进行更加详细的工作,而 malloc/free 不能。

相同点:

  1. 都用来申请堆空间
  2. 需要成对出现,否则会造成内存泄漏



常考题2:malloc的底层实现?free如何回收内存?

malloc从堆里面获得空间。也就是说函数返回的指针是指向堆里面的一块内存。操作系统中有一个记录空闲内存地址的链表。当操作系统收到程序的申请时,就会遍历该链表,然后就寻找第一个空间大于所申请空间的堆结点,然后就将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。

malloc函数来进行内存分配,分配的内存在进程管理的堆上,这一部分内存由程序员自己管理,内核本身不会插手。但是内核会为进程使用的代码和数据空间维护一个当前位置值brk,这个值会保存在每个进程的数据结构中,它指出了进程代码和数据(包括动态分配的数据空间)在进程地址空间中的末端位置,当使用malloc函数分配内存时,会通过系统调用brk()将需要新增的内存空间长度通知内核,内核代码根据malloc所提供的信息来更新brk的值,但此时并不为新申请的空间映射物理内存页面。只有当程序寻址到某个不存在的物理页面时,内核才进行相关的物理内存页面的映射操作

当进程寻址的某个数据所在的页面不存在,并且该页面所处的位置属于进程的堆范围,cpu会产生一个缺页异常,通过异常处理程序为指定的页面分配并映射一页的物理内存。对于用户程序申请的内存的字节长度以及在物理页面中的具体位置由malloc函数管理。该函数会具体记录用户程序使用了一页内存中的字节数,剩下的容量保留给程序再次申请内存时使用。

当用户使用内存释放函数 free() 动态释放已申请的内存块时,c库中的内存管理函数会把释放的内存块标记为空闲,备与程序再次申请的时候使用。在这个过程中内核为进程分配的物理页面并不会被释放。只有当整个进程结束时内核才会全面回收已经分配到该进程空间范围的所有物理内存页面。

因此可以认为当我们调用free函数释放某一块区域的内存时,free只是将这一块内存标记为空闲,实际上这一块物理内存还是属于该进程的,只有当整个进程结束后,才会全面回收这一块物理内存页面

摘自【linux下malloc与free机制解析】



常考题3:什么是内存泄漏,内存溢出,内存踩踏,野指针?

内存泄漏(Memory Leak) 是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。

内存溢出(Out Of Memory,简称OOM) 是指应用系统中存在无法回收的内存或使用的内存过多,最终使得程序运行要用到的内存大于能提供的最大内存。此时程序就运行不了,系统会提示内存溢出,有时候会自动关闭软件,重启电脑或者软件后释放掉一部分内存又可以正常运行该软件,而由系统配置、数据流、用户代码等原因而导致的内存溢出错误,即使用户重新执行任务依然无法避免

内存踩踏(Memory overlay),也叫内存覆盖,一般是数组越界,字符串操作越界,栈指针操作越界,操作了释放掉了的指针,对资源保护控制不当,使内存管理异常,使用了其他地方的内存或free的内存。

野指针,就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)指针变量在定义时如果未初始化,其值是随机的,指针变量的值是别的变量的地址,意味着指针指向了一个地址是不确定的变量,此时去解引用就是去访问了一个不确定的地址,所以结果是不可知的



最后

既然 new/delete 的功能完全覆盖了malloc/free,为什么C++还保留 malloc/free 呢? 因为C++程序经常要调用C函数,而C程序只能用 malloc/free 管理动态内存。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值