C语言里内存分配
一、C 语言程序在内存里的布局大致是text┌─────────────┐ 高地址 │ 栈 │ ← 局部变量、函数调用帧 ├─────────────┤ │ 堆 │ ← malloc 动态分配 ├─────────────┤ │ 数据段 │ ← 全局变量、静态变量 ├─────────────┤ │ 代码段 │ ← 函数的机器指令只读 └─────────────┘ 低地址注意栈和堆是“相向生长”的中间是空闲区域。二、每一块到底存什么1. 代码段.text存的是函数的机器指令CPU 执行的二进制代码什么时候有程序加载时就固定能不能改❌ 只读修改会段错误谁管操作系统加载器void func() { ... } // func 的代码在代码段2. 数据段.data.bss存的是全局变量、静态变量什么时候有程序启动时分配进程结束才释放能不能改✅ 能读写int global 10; // 数据段已初始化 static int count 0; // 数据段已初始化 static int x; // 数据段未初始化在 .bss重要.data存已初始化的全局/静态变量.bss存未初始化的全局/静态变量默认初始化为03. 堆Heap存的是动态分配的内存malloc、calloc、realloc什么时候有你调用malloc时分配free时释放能不能改✅ 能读写谁管程序员手动malloc/freeint *p malloc(10 * sizeof(int)); // 堆上分配 40 字节 free(p); // 堆上释放4. 栈Stack存的是局部变量、函数参数、函数返回地址、栈帧信息什么时候有函数调用时分配函数返回时自动释放能不能改✅ 能读写谁管编译器自动管理压栈 / 弹栈void func() { int x 10; // 栈上分配 int y 20; // 栈上分配 } // 函数返回x 和 y 自动释放三、用代码更好的了解#include stdio.h #include stdlib.h int global 100; // 数据段.data void func(int a) { // a 在栈上 static int count 0; // 数据段.data int b 20; // 栈上 int *p malloc(4); // p 在栈上指向的内存4字节在堆上 count; printf(%d %d %d\n, a, b, count); // 注意p 没 free内存泄漏 } int main() { func(10); return 0; }内存分布global→ 数据段count→ 数据段静态变量func的代码 → 代码段a、b、p→ 栈malloc(4)→ 堆4 字节四、为什么栈和堆要“相向生长”栈向下增长往低地址堆向上增长往高地址中间的空闲区域可以灵活分配充分利用内存空间如果它们同向增长其中一个很快会耗尽空间。五、常见的错误和后果错误行为影响递归太深栈溢出Stack Overflowmalloc不free内存泄漏堆耗尽返回局部变量的地址悬垂指针栈已释放越界写数组可能破坏栈帧或堆结构 → 段错误六、总结表区域存什么谁管生命周期代码段函数指令编译器 OS程序启动 → 结束数据段全局 / 静态变量编译器 OS程序启动 → 结束堆malloc分配的内存程序员你malloc→free栈局部变量、参数编译器自动函数调用 → 返回