**C/C++**内存分布
可执行程序的****段头表



可执行程序加载进内存的段大概有代码段(.text),数据段(.data .bss),只读数据段(.rodata),静态变量和全局变量在数据段中存储,如果初始化了那就是在.data节,如果没初始化那就是在.bss节,字符串常量在只读数据段存储,代码指令在代码段存储
【说明】
- 栈 又叫栈段 --存储 非静态局部变量 / 函数参数 / 返回值等等,栈是向下增长的。
- 内存映射段(共享段) 用于加载一个共享的动态库,用户还可使用系统接口创建共享内存映射在共享段,做进程间通信。
- 堆 用于程序运行时动态内存分配,堆是可以上增长的。
- 数据段 -- 存储全局数据和静态数据。
- 代码段 --代码指令
6、**只读数据段:**在代码段和数据段之间,存储字符串常量,虚函数表这些
C****语言中动态内存管理方式

| 函数名 | 主要功能 | 初始化内容 | 参数特点 | 核心区别 |
|---|---|---|---|---|
**malloc** |
分配指定字节数的内存块 | 内容未初始化,是随机值 | 1个参数:所需内存的总字节数 (size_t size) |
只分配,不初始化,效率相对较高 |
**calloc** |
为数组分配内存,并初始化为零 | 内容自动初始化为零 | 2个参数:元素个数 (size_t num) 和每个元素大小 (size_t size) |
分配并初始化为零,适合数组 |
**realloc** |
调整已分配内存块的大小 | 原有数据保留,新增空间不初始化 | 2个参数:原内存指针 (void *ptr) 和新的大小 (size_t size) |
调整已有内存块的大小,可能移动数据 |
**free** |
释放动态分配的内存 | - | 1个参数:要释放的内存指针 (void *ptr) |
释放内存,防止内存泄漏 |
动态内存函数详解
1、malloc 的功能是申请一块连续可用的空间。如果分配成功,它返回指向这块空间起始位置的指针;如果失败(如内存不足),则返回 NULL。因此,在使用 malloc返回的指针之前,务必检查其是否为 NULL 。由于它分配的内存是未初始化的,如果直接使用,内容会是随机值,通常需要手动初始化(例如使用 memset)。
2、calloc 在功能上类似于 malloc,但有两个主要区别:一是参数形式不同,它接受元素个数和每个元素的大小;二是它分配内存后,会自动将内存中的所有位初始化为零。这使得 calloc特别适合为数组或需要初始清零的数据结构分配内存。当然,这种初始化也会带来微小的性能开销。
3、realloc 用于调整一块已经通过 malloc, calloc或 realloc分配的内存的大小。它的行为比较复杂:
-
如果原内存块之后有足够 的连续空闲空间,
realloc会直接在原位置扩展内存块,并返回与原指针相同的地址。 -
如果原内存块之后没有足够 的空间,
realloc会寻找一个新的足够大的内存块,将旧数据复制 到新位置,然后自动释放旧的内存块,最后返回指向新内存块的指针。 -
如果调整大小失败 ,它会返回
NULL,而此时原来的内存块仍然有效,原来的指针也有效。因此,一个良好的实践是先用一个临时指针接收realloc的返回值,确认非NULL后再赋值给原指针,避免内存泄漏。
free 专门用于释放由上述三个函数分配的内存。它的参数是待释放内存块的起始指针。free不会将指针本身置为 NULL ,因此释放后,该指针会变成一个"野指针"。为了安全起见,在调用 free后,应立即将指针显式设置为 NULL,防止后续误用。
**C++**内存管理方式
通过 new/new[ ] 和 delete/delete[ ] 操作符进行动态内存管理 。
C++ 动态内存管理详讲-CSDN博客
定位new表达式
定位 new 表达式是在 已分配的原始内存空间中调用构造函数初始化一个对象 。
使用格式:
new (place_address) type 或者 new (place_address) type(initializer-list)
place_address 必须是一个指针, initializer-list 是类型的初始化列表
使用场景:
定位 new 表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如果是自定义类型的对象,需要使用new 的定义表达式进行显示调构造函数进行初始化。


malloc/free和new/delete****的区别
malloc/free 和 new/delete 的共同点是:都是从堆上申请空间,并且需要用户手动释放。
不同的地方是:
- malloc 和 free 是函数, new 和 delete 是操作符
- malloc 申请的空间不会初始化, new 可以初始化
- malloc 申请空间时,需要手动计算空间大小并传递, new 只需在其后跟上空间的类型即可, 如果是多个对象,[] 中指定对象个数即可
- malloc 的返回值为 void*, 在使用时必须强转, new 不需要,因为 new 后跟的是空间的类型
- malloc 申请空间失败时,返回的是 NULL , new失败时会抛出异常
- 申请自定义类型对象时, malloc/free 只会开辟/释放空间,不会调用构造函数与析构函数,而 new 在申请空间后会调用构造函数完成对象的初始化,delete 在释放空间前会调用析构函数完成空间中资源的清理
内存泄漏
什么是内存泄漏
内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况
内存泄漏的危害
长期运行的程序出现内存泄漏,可用的内存会越来越少,最后程序会卡死