5.4 内存管理

本篇学习栈与堆的区别,以及 `malloc`、`calloc`、`realloc`、`free` 的基本用法,并能安全完成动态内存申请与释放。

内存管理

概念说明

C 语言允许程序员主动向堆区申请和释放内存。 这让程序能处理运行时才知道大小的数据,但也意味着你要自己负责释放资源和避免非法访问。

学动态内存时,光记住函数名远远不够。 更重要的是建立“资源所有权”的意识:是谁申请的、谁负责释放、失败时怎么兜底、释放后还能不能继续使用旧地址。

还可以先区分两类常见内存:

  • 自动存储区:例如普通局部变量,通常跟随作用域自动创建和销毁。
  • 堆区:通过 malloc 这类接口显式申请,必须手动释放。

语法/规则

  1. malloc(size) 按字节申请一块未初始化的内存。
  2. calloc(count, size) 会申请并清零一块内存。
  3. realloc(ptr, new_size) 用于调整原内存块大小,可能返回新地址。
  4. free(ptr) 释放动态内存;释放后不应再继续使用该地址。
  5. 申请内存后必须先检查返回值是否为 NULL
  6. 调整内存大小时,最好先用临时指针接收 realloc 返回值,避免原指针丢失。
  7. 动态数组的字节数通常写成 元素个数 * sizeof(元素类型),而不是手写魔法数字。

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int *nums = malloc(3 * sizeof(int));
    if (nums == NULL) {
        return 1;
    }

    nums[0] = 10;
    nums[1] = 20;
    nums[2] = 30;

    int *tmp = realloc(nums, 5 * sizeof(int));
    if (tmp == NULL) {
        free(nums);
        return 1;
    }
    nums = tmp;

    nums[3] = 40;
    nums[4] = 50;

    printf("sum = %d\n", nums[0] + nums[1] + nums[2] + nums[3] + nums[4]);

    free(nums);
    nums = NULL;
    return 0;
}

输出结果:

1
sum = 150

常见错误

  1. 申请了内存却忘记释放,造成内存泄漏。
  2. free 之后继续读写同一块内存,形成 use-after-free。
  3. 申请大小写错,例如忘了乘 sizeof(元素类型),导致缓冲区过小。
  4. 直接把 realloc 返回值赋给原指针,失败时把原地址也丢了。
  5. 对同一块内存重复 free,或者释放了根本不是动态申请得到的地址。
本文禁止转载
使用 Hugo 构建
主题 StackJimmy 设计 由 Hobin 魔改
最近构建时间:2026-04-17 19:07:48 CST
载入天数...载入时分秒...
发表了 1 篇文章 · 发表了 152 篇笔记 · 总计 18 万 0 千字