C++ 内存分布详解
C++程序在运行时使用的内存通常分为以下几个主要区域,理解这些内存区域的特性对于编写高效、安全的代码至关重要。
一、内存五大分区
1. 栈区(Stack)
- 存储内容:
- 局部变量
- 函数参数
- 函数调用信息(返回地址、寄存器值等)
- 特性:
- 由编译器自动分配和释放
- 后进先出(LIFO)结构
- 内存空间有限(通常几MB)
- 访问速度快
- 示例:
void func()
{
int x = 10; // x存储在栈上
char buffer[1024]; // 数组存储在栈上
}
2. 堆区(Heap)/自由存储区(Free Store)
- 存储内容:
- 动态分配的内存(new/malloc)
- 特性:
- 程序员手动控制分配和释放
- 空间大(受系统内存限制)
- 访问速度较慢
- 需要防止内存泄漏
- 示例:
int* p = new int(42); // 在堆上分配
delete p; // 手动释放
3. 全局/静态存储区
- 细分区域:
- .data段:已初始化的全局变量和静态变量
- .bss段:未初始化的全局变量和静态变量(程序启动时自动初始化为0)
- 特性:
- 程序启动时分配,结束时释放
- 生命周期贯穿整个程序
- 默认初始化为0(未显式初始化时)
- 示例:
int globalVar = 1; // .data段
static int staticVar; // .bss段(初始化为0)
void func()
{
static int localStatic = 2; // .data段
}
4. 常量存储区
- 存储内容:
- 字符串字面量
- const修饰的全局变量(C++中可能优化到此处)
- 特性:
- 只读内存
- 程序生命周期内存在
- 示例:
const char* str = "Hello"; // "Hello"在常量区
const int MAX = 100; // 可能存储在常量区
5. 代码区(Text Segment)
- 存储内容:
- 可执行代码(函数体)
- 类成员函数
- 特性:
- 只读内存
- 共享内存(多个实例可共享相同代码)
二、C++对象内存布局
1. 普通类对象
class Example
{
int x; // 成员变量
static int y; // 不占对象空间(在全局区)
public:
void func() {} // 不占对象空间(在代码区)
};
- 内存占用:仅包含非static成员变量(本例中sizeof(Example) == sizeof(int))
2. 继承与多态
class Base
{
int a;
virtual void foo() {}
};
class Derived : public Base
{
int b;
};
- 虚函数表指针(vptr)位于对象起始位置
- 继承的成员变量在前,派生类新增成员在后
三、内存对齐(Memory Alignment)
1. 对齐原则
- 基本类型按其大小对齐(int按4字节,double按8字节等)
- 结构体/类对齐按其最大成员对齐
- 可使用 alignas 指定对齐方式
2. 示例
struct AlignmentExample
{
char a; // 1字节
// 3字节填充
int b; // 4字节
double c; // 8字节
}; // 总大小:16字节
四、动态内存管理
1. new/delete 原理
- new 操作:
1. 调用operator new分配内存
2. 调用构造函数
- delete 操作:
1. 调用析构函数
2. 调用operator delete释放内存
2. 自定义内存管理
class CustomAlloc
{
public:
static void* operator new(size_t size)
{
void* p = customAllocate(size);
return p;
}
static void operator delete(void* p)
{
customDeallocate(p);
}
};
五、常见内存问题
1. 内存泄漏:分配后未释放
2. 野指针:访问已释放内存
3. 越界访问:数组/缓冲区溢出
4. 重复释放:同一内存多次delete
5. 内存碎片:频繁分配释放导致
六、工具与技术
1. 智能指针:unique_ptr, shared_ptr
2. 内存池:定制分配器
3. 分析工具:
- Valgrind(Linux)
- Dr. Memory(Windows)
- AddressSanitizer(GCC/Clang)
理解C++内存分布有助于:
- 编写更高效的代码
- 避免内存相关错误
- 优化程序性能
- 设计更好的数据结构