C/C++内存管理

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. 事前预防:最理想的情况,有良好的编码习惯,使用智能指针等。

相关推荐

  1. 内存管理

    2024-07-12 14:32:01       34 阅读
  2. C/C++——内存管理

    2024-07-12 14:32:01       60 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-12 14:32:01       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-12 14:32:01       71 阅读
  3. 在Django里面运行非项目文件

    2024-07-12 14:32:01       58 阅读
  4. Python语言-面向对象

    2024-07-12 14:32:01       69 阅读

热门阅读

  1. Visual Studio 常用快捷键

    2024-07-12 14:32:01       24 阅读
  2. 【常用知识点-Linux】scp命令

    2024-07-12 14:32:01       21 阅读
  3. 用Redis写一个IP限流器

    2024-07-12 14:32:01       23 阅读
  4. 天童美语:推荐给孩子的人文历史纪录片

    2024-07-12 14:32:01       26 阅读
  5. 网站安全需求分析与安全保护工程

    2024-07-12 14:32:01       20 阅读
  6. 小米官网的数据是怎么优化的?

    2024-07-12 14:32:01       21 阅读
  7. 支付通道安全:应对黑客攻击的策略与实践

    2024-07-12 14:32:01       22 阅读
  8. Markdown 的详细语法介绍与使用

    2024-07-12 14:32:01       19 阅读