C/C++内存管理

10 篇文章 0 订阅

1. C/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";
	 
	 const 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);
}

1.1 分辨

四个选项:栈、堆、静态区/全局区(数据段)、常量区(代码段)。

globalVar在哪里? 静态区
staticGlobalVar在哪里?静态区
staticVar在哪里?静态区
localVar在哪里?
num1 在哪里?

char2在哪里?
*char2在哪里?
pChar3在哪里?
*pChar3在哪里?常量区
ptr1在哪里?
*ptr1在哪里?

在这里插入图片描述

  1. 内核空间:用户代码不能读写;
  2. 栈区:又叫堆栈,栈是向下增长的(从高地址到低址值向下使用);
  3. 内存映射段:文件映射、动态库、匿名映射;
  4. 堆区:程序运行时动态内存分配,可以向上增长。
  5. 数据段:存储全局变量和静态变量;
  6. 代码段:存储可执行代码和常量。

1.2 sizeof与strlen区别

sizeof(num1) 40
sizeof(char2) 5
strlen(char2) 4
sizeof(pChar3) 4或8
strlen(pChar3) 4
sizeof(ptr1) 4或8

sizeof计算内存存储大小;strlen计算字符串长度,不包含\0。

2. C的内存管理

申请内存:malloc、calloc、realloc;
释放内存:free

面试题:

  1. malloc、calloc、realloc区别是什么?
    malloc仅仅是申请一块内存;
    calloc底层调用malloc申请一块内存,但还会额外对变量进行默认初始化;
    realloc在原申请的内存基础上进行内存扩容,如果后面的内存空间够,则原地扩容;
    后面的内存空间不够,则异地扩容,返回新的内存地址。

  2. malloc实现原理
    这个太难了,先不研究。

3. C++的内存管理

C++可以继续使用C的malloc、calloc、realloc和free,C的内存管理使用起来很麻烦,C++有自己的内存管理方式,使用起来很方便。

3.1 new与delete、delete[]

  1. new和delete都是操作符,new申请内存,delete/delete[]释放内存。
int* pa = new int;
int* pb = new int(12); // 动态申请内存并初始化
int* pArr = new int[10]; // 动态申请40个字节内存空间
delete pa;
delete pa;
delete[] pArr;
  1. 申请/释放单个不连续的内存使用new和delete,申请/释放多个连续的内存使用new[]和delete[]。
  2. new[]和delete[]底层多次调用new和delete完成申请或释放内存。

3.2 operator new与operator delete

  1. operator new和operator delete是C++提供的全局函数;
  2. new和delete是操作符,new和delete调用它们俩完成申请和释放内存;
  3. operator new实际是通过malloc来申请内存,operator delete最终也是通过free来释放内存。

4. malloc/free与new/delete区别

  1. new/delete对于自定义类型申请空间,会调用构造函数(new之后)和析构函数(delete之前),而malloc/free做不到。
  2. 对于内置类型,两者除了使用上有差别,效果一样。
  3. malloc/free是函数,new/delete是操作符。
  4. new申请内存失败会抛异常,malloc申请失败返回NULL。
  5. malloc申请的内存空间不会默认初始化,new会。
  6. malloc申请内存需要计算并传递内存大小,new不需要。
  7. malloc返回值是void*,接收时需要强转成需要的类型,new的返回值不需要强转。

5. 内存泄露

内存泄露:程序未能释放不再使用的内存。

不是指物理上的消失,而是因为这块内存不再使用,程序失去对这块内存的控制,造成内存浪费。对于长期运行的程序而言,如服务器、操作系统,内存泄漏造成的影响很大,最终程序响应越来越慢,导致机器卡死,所以及时释放不需要再使用的内存至关重要。

需要注意的是避免内存泄露的同时,也要避免使用野指针。

5.1 分类

  1. 堆内存泄露(Heap Leak):malloc/calloc/realloc/new申请的内存没有被free/delete。
  2. 系统资源泄露:程序使用系统分配的资源,如套接字、文件描述符、管道等,之后没有使用对应的函数释放资源。

5.2 避免内存泄露

  1. 检测内存泄漏:VS环境下使用Windows提供的_CrtDumpMemoryLeaks()函数,会提示泄露多少字节,但没有准确的位置信息。
  2. 内存泄露检测工具:很多工具都不靠谱。Linux下几款C++程序中的内存泄露检查工具 ----- 内存泄露检测工具比较
  3. 事前预防:最理想的情况,有良好的编码习惯,使用智能指针等。
  • 23
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

念来过倒字名qwq

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

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

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

打赏作者

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

抵扣说明:

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

余额充值