C 语言内存管理
概述
C 语言的内存管理是系统编程的核心技能。与高级语言不同,C 不提供自动垃圾回收,程序员需要手动管理内存的分配和释放。
内存区域划分
C 程序运行时的内存分为以下几个区域:
栈区(Stack)
- 由编译器自动管理
- 存储局部变量、函数参数、返回地址
- 分配释放速度极快,遵循 LIFO 原则
- 大小有限,通常默认 1~8 MB
堆区(Heap)
- 由程序员手动管理
- 使用 malloc/calloc/realloc 分配,free 释放
- 空间大,但容易产生碎片
- 分配失败时返回 NULL
全局/静态区(Data Segment)
- 存储全局变量和 static 变量
- 程序启动时分配,程序结束时释放
- 分为已初始化段(.data)和未初始化段(.bss)
代码区(Text Segment)
- 存储编译后的机器指令
- 只读,防止程序意外修改自身代码
核心函数
| 函数 | 功能 | 头文件 |
|---|---|---|
malloc(size) |
分配指定字节数的内存,不初始化 | stdlib.h |
calloc(n, size) |
分配 n*size 字节并初始化为 0 | stdlib.h |
realloc(ptr, size) |
调整已分配内存的大小 | stdlib.h |
free(ptr) |
释放之前分配的内存 | stdlib.h |
常见错误
内存泄漏
分配后忘记释放,导致程序持续占用内存。
悬空指针
释放内存后继续使用指针,指向已回收的地址。
重复释放
对同一块内存调用 free 两次,导致未定义行为。
越界访问
访问分配区域之外的内存,可能破坏堆元数据。
分配失败未检查
malloc 返回 NULL 时未检查,直接解引用导致崩溃。
最佳实践
- malloc 后立即检查返回值
- free 后将指针置为 NULL
- 谁分配谁释放,保持所有权清晰
- 使用工具如 Valgrind 检测内存问题
- 考虑使用内存池减少碎片
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 lbq开发日志!