C/C++内存管理

发布于:2025-05-01 ⋅ 阅读:(49) ⋅ 点赞:(0)

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 字节,并处为 0
  • realloc(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 是较高级的技术,但对性能怪兽等有符合性应用

如果需要给出相关分区图视化或其他扩展,我可以继续添加简洁图视化图。