C 语言从 0 入门(二十二)|内存四区:栈、堆、全局、常量区深度解析

大家好,我是网域小星球。

很多同学学到指针、动态内存、变量作用域时都会困惑:

  • 为什么局部变量出函数就失效?
  • 为什么 malloc 出来的内存要手动 free
  • 为什么字符串常量不能改?
  • 野指针、内存泄漏到底是怎么产生的?

答案都在内存四区 里。这一章不讲花哨语法,而是讲程序运行的底层原理,搞懂它,指针和内存相关的 BUG 你一眼就能看懂。

目录

一、本章学习目标

二、程序内存四区概览

三、栈区(stack)

特点

存放内容

典型坑点

四、堆区(heap)

特点

存放内容

[五、全局 / 静态区](#五、全局 / 静态区)

特点

存放内容

[六、常量区 & 代码区](#六、常量区 & 代码区)

特点

存放内容

七、四区一张表总结

[八、高频面试 & BUG 原理](#八、高频面试 & BUG 原理)

九、本章核心总结

下期预告


一、本章学习目标

  1. 认识 C 程序的四大内存区域:栈区、堆区、全局 / 静态区、常量区
  2. 知道每种变量存在哪里、生命周期多长
  3. 理解栈与堆的区别,彻底搞懂动态内存
  4. 明白野指针、内存泄漏、常量不能修改的本质
  5. 为后续写稳定、少 BUG 的程序打下底层基础

二、程序内存四区概览

程序运行时,操作系统会给它分配一块内存,主要分为 4 个区域:

  1. **栈区(stack)**局部变量、函数形参,由系统自动分配、自动释放。

  2. 堆区(heap) 动态内存(malloc/calloc/realloc),手动申请、手动释放。

  3. 全局 / 静态区(data segment) 全局变量、静态变量(static),程序整个运行期间都存在。

  4. **常量区 / 代码区(text & rodata)**代码指令、字符串常量、const 常量,只读不可修改。


三、栈区(stack)

特点

  • 系统自动管理,不需要手动申请释放
  • 空间小、分配速度快
  • 遵循后进先出
  • 函数结束时,局部变量自动销毁

存放内容

  • 函数内部的非静态局部变量
  • 函数参数
  • 函数返回地址

示例:

cpp 复制代码
void func() {
    int a = 10;     // 栈上
    char arr[10];   // 栈上
}

// 函数结束,a 和 arr 自动被回收

典型坑点

返回栈内存地址:

cpp 复制代码
int *func() {
    int a = 10;
    return &a;  // 危险!
}

函数结束后 a 已经销毁,返回的地址变成野指针


四、堆区(heap)

特点

  • 手动申请(malloc)、手动释放(free
  • 空间大、速度相对慢
  • 生命周期由程序员控制
  • 不主动释放会造成内存泄漏,程序结束后由系统回收

存放内容

  • malloc / calloc / realloc 申请的内存

示例:

cpp 复制代码
int *p = (int*)malloc(4 * sizeof(int));
// 手动释放
free(p);
p = NULL;  // 避免野指针

五、全局 / 静态区

特点

  • 程序运行期间一直存在
  • 默认初始化为 0
  • 作用域看定义位置

存放内容

  1. 全局变量:函数外定义
  2. 静态变量static 修饰的变量

示例:

cpp 复制代码
int g_a = 10;   // 全局区

void func() {
    static int s_b = 20;  // 静态区
}

static 局部变量特点:

  • 只初始化一次
  • 函数结束不销毁
  • 下次进函数值还在

六、常量区 & 代码区

特点

  • 只读,不能修改
  • 修改会直接程序崩溃

存放内容

  • 程序代码指令
  • 字符串常量
  • const 修饰的全局常量

典型坑点:

cpp 复制代码
char *p = "hello";  // "hello" 在常量区
p[0] = 'H';         // 崩溃!

但下面这个没问题,因为在栈上:

cpp 复制代码
char arr[] = "hello";
arr[0] = 'H';  // 正常

七、四区一张表总结

区域 存放内容 生命周期 管理方式 读写
栈区 局部变量、形参 函数内 系统自动 读写
堆区 malloc 内存 手动控制 手动 free 读写
全局区 全局 / 静态变量 整个程序 系统自动 读写
常量区 字符串、代码 整个程序 系统 只读

八、高频面试 & BUG 原理

  1. 野指针指向栈变量释放、堆内存已 free、未初始化的指针。

  2. 内存泄漏malloc 后没有 free,一直占着内存。

  3. 程序崩溃修改常量区、越界访问、野指针解引用。

  4. static 作用改变生命周期(不改变作用域)。


九、本章核心总结

  1. 栈:自动、临时、小空间
  2. 堆:手动、持久、大空间
  3. 全局 / 静态:全程存在、默认 0
  4. 常量区:只读,不能改
  5. 搞懂四区 = 搞懂内存生命周期 = 少写 90% 指针 BUG

下期预告

下一篇我们讲编译之前的预处理指令,学会宏定义、文件包含、条件编译,写更通用、跨平台的代码。

相关推荐
晓纪同学2 小时前
EffctiveC++_第三章_资源管理
开发语言·c++·算法
蚊子码农2 小时前
每日一题--C语言指针与内存泄漏:一道小问题的深度复盘
c语言·开发语言
Fanfanaas2 小时前
Linux 系统编程 进程篇(一)
linux·运维·服务器·c语言·开发语言·网络·学习
星辰徐哥2 小时前
ARP缓存表:作用、查看方法与刷新技巧
开发语言·缓存·php
ego.iblacat2 小时前
lvs 集群部署
开发语言·php·lvs
沐雪轻挽萤2 小时前
6. C++17新特性-编译期 if 语句 (if constexpr)
开发语言·c++
水云桐程序员2 小时前
C语言编程基础,输入与输出
c语言·开发语言·算法
爱代码的小黄人2 小时前
MATLAB中for循环实现递减遍历(通用方法)
开发语言·matlab
weixin_704266052 小时前
手机体检预约系统开发解析
java·开发语言