C++内存分布介绍

今天更新一下C++内存分布和管理的东西,这玩意就是考验你的基础扎不扎实

1.C++内存分布

直接上图

 上图右边这段最好是牢记

内核空间就不说了,咱不管

栈区:那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区。函数调用建立栈帧,参数、函数中局部变量都存在栈帧中,栈是向下增长的,向下增长的意思是:从栈申请的内存地址会越来越小,在栈区当中是先使用高地址再使用低地址。

内存映射段也不管

堆区:一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。理论上而言,后malloc的内存地址比先malloc的要大,但是也不一定,但是不一定,因为有可能下一次申请的是之前其他空间释放回来的,这个区一般都很大,在32位系统下,可以占差不多3G的样子

数据段:全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的(DATA段)和未初始化的(BSS段),在C++里面没有这个区分了,它们共同占用同一块内存区

代码段:可执行代码其实就是二进制指令,这里是存放二进制代码的。通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许修改程序。 在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。

看完了右边再来看左边,左边的代码如下:

下列变量分别存储在哪

int globalVar = 1;//全局变量
static int staticGlobalVar = 1;//静态数据
void Test()
{
    static int staticVar = 1;//静态数据
    int localVar = 1;//栈帧里面
    int num1[10] = {1, 2, 3, 4};//栈
    char char2[] = "abcd";
    char* pChar3 = "abcd";
    int* ptr1 = (int*)malloc(sizeof (int)*4);
    int* ptr2 = (int*)calloc(4, sizeof(int));
    int* ptr3 = (int*)realloc(ptr2, sizeof(int)*4);
    free (ptr1);
    free (ptr3);
}

globalVar是全局变量所以它在数据段

staticGlobalVar是静态变量所以它在数据段

staticVar是静态变量所以它在数据段

localVar创建在test函数栈帧中,它是局部变量,在栈区

num1是数组,在函数栈帧中创建,存储在栈区

char2是数组,在函数栈帧中创建,存储在栈区

*char2拿到的是字符a的地址,因为char2是数组,里面的元素也是存储在栈帧里面的,所以*char2也在栈区

pchar3是指针变量,存储在栈区,它指向字符串的首字符地址

*pchar3是常量字符a,常量字符串是存储在常量区的,就是在代码段

ptr1是指针变量,他存储在栈区

ptr1指向的内存空间是malloc出来的,所以*ptr1是在堆区

2.C++内存管理

这里要回忆一下C语言中动态内存管理的知识:malloc  realloc和calloc分别是什么?

calloc等价于malloc+memest(0),开空间+初始化为0

realloc是对malloc或calloc的空间进行扩容

接下来就引入C++中的内存管理,就是new和delete

注意:malloc和free是库函数,而new和delete只是操作符

void Test()
{
    //C语言 malloc等是库函数
    int* p1 = (int*)malloc(sizeof(int));
    free(p1);
    
    //C++ new/delete是操作符
    // 动态申请一个int类型的空间
    int* ptr4 = new int;
    // 动态申请一个int类型的空间并初始化为10
    int* ptr5 = new int(10);
    delete ptr4;
    delete ptr5;
}

那么两者的区别是什么?

如果动态申请的对象是内置类型,用malloc和new没有区别,如果动态申请的对象是自定义类型,有区别,因为new和delete不仅仅会开空间/释放空间,还会调用构造函数和析构函数

这里注意一点在new数组的时候,delete一定要加[],否则可能出错

接下来还有一点要知道的是operator new和operator delete函数

new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间

我们在new一个对象T时,其实编译器会这样做:

1、申请内存,调用operator new(底层其实是将malloc的封装实现)

2、调用构造函数

在delete时,编译器会这么做:

1、调用T的析构函数

2、调用operator delete(底层其实是将free的封装实现)

说完了调用,那么如果调用失败呢?

如果是malloc,就会返回NULL;

如果是new,就会抛一个异常出来

对于上述提到的自定义类型,new和delete的原理是什么呢?

new的原理
调用operator new函数申请空间
在申请的空间上执行构造函数,完成对象的构造
delete的原理
在空间上执行析构函数,完成对象中资源的清理工作
调用operator delete函数释放对象的空间
new T[N]的原理
调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申

在申请的空间上执行N次构造函数
delete[]的原理
在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间

内存泄漏

最后一点 malloc和new的使用就必然设计到内存泄漏的问题

内存泄漏:在堆上申请了的空间,在我们不用了以后也没有释放,就存在内存泄漏,因为你不用了,也没有还给系统,别人也用不了

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

何以过春秋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值