C/C++内存分布详解
C/C++ 中的内存分布后可以大致分为以下几部分:
1. 代码区 (Text Segment)
- 存放程序代码,通常是只读区域,无法写入
- 如果试图写入,会导致系统错误(如切换重启、核心崩溃)
2. 全局和静态区 (Data Segment)
- 存放全局变量和 static 变量
- 包括两部分:
- 初始化区:已给初始值的变量
- BSS(未初始化)区:未给值的全局或 static 变量
- 系统在运行期初始化时为 BSS 区设置为 0
3. 堆区 (Heap)
- 动态分配的内存,待用户手动释放
- 从低地址向上增长,不同于栈(从高地址向下)
- 如果释放后未当地处理,就会造成内存泄漏
4. 栈区 (Stack)
- 函数调用时会分配栈字段,释放由系统管理
- 常用于局部变量、函数参数、微临时内存
- 从高地址向低分配,和堆区在地址上是对向增长,方便加载后续内存
5. 常量区 / 只读区 (Readonly Data)
- 存放不可修改的常量、字符串定值
- 如果尝试修改这些区,会引发系统错误
C语言中的动态内存管理
1. malloc / calloc / realloc
malloc(size_t size)
:分配 size 字节,内容未初始化calloc(size_t n, size_t size)
:分配 n*size 字节,并处为 0realloc(void* ptr, size_t size)
:重新分配内容,并保留旧数据
2. free
free(void* ptr)
用于释放堆内存,很重要!- 一旦释放后继续使用,就是释放后访问(Dangling Pointer)
3. 内存泄漏
- 如果 malloc 后未 free,或 realloc 异常丢失原指针,都可能导致泄漏
4. 指针安全
- malloc 分配后需要检查是否为 NULL
C++ 中的动态内存管理
1. new / delete
int* p = new int(10); // 分配 4 字节,初始化为 10
int* arr = new int[10]; // 分配 40 字节,未初始化delete p; // 释放单个对象
delete[] arr; // 释放数组
2. 特性
- new 调用 operator new,然后调用构造函数
- delete 调用析构函数,然后调用 operator delete
3. 和 malloc/free 对比
方式 | 分配内容 | 实际调用 | 是否调用构造/析构 |
---|---|---|---|
malloc | 只分配空间 | malloc | 否 |
new | 分配 + 构造 | operator new | 是 |
delete | 析构 + 释放 | operator delete | 是 |
free | 只释放 | free | 否 |
operator new 与 operator delete
1. 原型
void* operator new(std::size_t size);
void operator delete(void* ptr);
2. 重写用法
class MyClass {
public:void* operator new(size_t size) {std::cout << "custom new\n";return ::operator new(size);}void operator delete(void* ptr) {std::cout << "custom delete\n";::operator delete(ptr);}
};
3. 应用场景
- 自定义内存模型(内存混合、自定义分配器)
- 辅助跟踪内存分配释放
new/delete 实现原理
1. new
- 约翰:
T* p = new T(args);
实际等价于:
void* raw = operator new(sizeof(T));
T* p = new(raw) T(args); // 应用 placement-new
2. delete
约翰:
delete p;
实际等价于:
p->~T();
operator delete(p);
定位型 new 表达式 (placement-new)
1. 格式
#include <new>
char buffer[sizeof(MyClass)];
MyClass* obj = new (buffer) MyClass(123);
2. 特点
- 指定地址分配
- 不分配新内存,而是在 buffer 中直接构造对象
- 用户需要确保 buffer 夠大,并手动析构:
obj->~MyClass();
3. 应用场景
- 内存混合(memory pool)
- 水平集成(arena allocation)
- 微控制内存分配等
结论
- 熟悉内存分区帮助理解指针、内存泄漏、函数调用机制
- 接触 C++
operator new
/delete
能帮助我们编写高性能内存模型 - placement-new 是较高级的技术,但对性能怪兽等有符合性应用
如果需要给出相关分区图视化或其他扩展,我可以继续添加简洁图视化图。