C语言逆向学习基础课 第2课:内存分配与释放的深度误区

一、课程导入

内存管理是C语言最核心、最考验专家级功底的能力,也是普通程序员与专家级程序员的关键分水岭。

本课聚焦动态内存分配与释放的各类深度误区,从根源讲解内存泄漏、重复释放、野指针、分配失败等致命问题,帮助你建立安全、规范、健壮的内存管理思维。

二、核心知识点详解

知识点1:内存分配函数使用误区

malloc/calloc/realloc 最容易出现三大错误:

  1. 分配后不校验是否成功,直接使用返回NULL的指针导致崩溃。

  2. 计算大小错误,少算字节数导致内存越界。

  3. realloc直接覆盖原指针,分配失败造成内存丢失。

这些错误在小型程序中不易暴露,但在高并发、长时间运行的系统中会造成严重故障。

知识点2:内存释放的深度陷阱

free() 使用不当会引发程序未定义行为:

  1. 重复释放:同一指针free两次,直接崩溃。

  2. 释放后不置空,指针变成悬空指针,再次使用造成非法访问。

  3. 释放非堆内存:释放栈变量、全局变量、常量区地址,造成严重错误。

  4. 只开辟不释放,造成内存泄漏,长期运行导致系统资源耗尽。

知识点3:内存泄漏的典型场景

  1. 函数内部分配内存,退出前未释放且未返回指针。

  2. 重新分配内存时未保存原地址,直接覆盖。

  3. 分支逻辑中,部分路径忘记释放。

  4. 循环内反复分配不释放。

内存泄漏是普通程序员最容易忽略、专家级程序员必须严格杜绝的问题。

三、实战案例与修正

案例1:malloc不校验 + 重复释放

错误代码:

C 复制代码
int *p = malloc(10 * sizeof(int));
*p = 100;
free(p);
free(p);

修正代码:

C 复制代码
int *p = malloc(10 * sizeof(int));
if (p == NULL) {
    return -1;
}
*p = 100;
free(p);
p = NULL;

案例2:realloc陷阱

错误代码:

C 复制代码
int *p = malloc(10);
p = realloc(p, 100);

修正代码:

C 复制代码
int *temp = realloc(p, 100 * sizeof(int));
if (temp != NULL) {
    p = temp;
}

案例3:安全释放宏(专家级写法)

C 复制代码
#define SAFE_FREE(ptr)  {free(ptr); ptr = NULL;}

统一释放规则,彻底避免重复释放与野指针。

四、课堂作业

  1. 找出以下代码的所有内存问题并修正:
C 复制代码
int *p = malloc(20);
p = realloc(p, 40);
free(p);
  1. 编写一个安全分配、安全使用、安全释放的完整函数。

  2. 描述内存泄漏对长期运行程序的危害。

五、课程总结

本课重点掌握:

  1. 分配必校验,释放必置空。

  2. 禁止重复释放、禁止释放非堆内存。

  3. realloc必须使用临时指针接收。

  4. 使用SAFE_FREE宏统一释放规范。

  5. 内存泄漏是专家级程序员必须杜绝的问题。

掌握这些规则,能让你从普通程序员快速升级为安全、稳定、高效的专家级C开发者。

六、核心关键词

malloc、calloc、realloc、free、内存泄漏、重复释放、悬空指针、安全释放、内存校验、堆内存


第1课作业答案:数组越界与指针操作基础陷阱 ------ 实战作业代码

实战作业代码

C 复制代码
#include <stdio.h>

int main() {
    // 定义长度为10的数组
    int arr[10];
    int i;

    // 循环赋值,严格不越界
    for (i = 0; i < 10; i++) {
        arr[i] = i + 1;
    }

    // 遍历输出所有元素
    printf("数组所有元素:");
    for (i = 0; i < 10; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    // 指针指向数组首元素
    int *p = arr;

    // 指针输出前3个元素,无野指针、无空指针
    printf("指针访问前3个元素:");
    for (i = 0; i < 3; i++) {
        printf("%d ", *(p + i));
    }
    printf("\n");

    return 0;
}

代码功能说明

本程序实现一个长度为10的int数组安全赋值与遍历输出,通过规范循环边界避免数组越界。程序先使用for循环为数组元素赋值1~10,再遍历输出全部元素;同时定义指针指向数组首地址,在确保指针有效、非野指针、非空指针的前提下,安全访问并输出数组前3个元素。整个过程严格遵守下标校验、指针初始化、指针安全解引用规则,强化C语言内存安全意识,帮助程序员从基础阶段养成专家级编码习惯。

注意事项

  1. 数组下标必须从0开始,循环条件必须使用 i < 长度,禁止使用 i <= 长度。

  2. 指针必须指向有效地址,禁止未初始化直接解引用。

  3. 访问指针时确保不超出数组范围,避免越界读写。

  4. 数组作为局部变量时,系统不会自动初始化,建议养成显式赋值习惯。

  5. 编写长期稳定运行的程序时,所有指针解引用前建议增加非空校验。

  6. 规范代码格式,便于后期调试与维护,符合专家级程序员工程化开发习惯。


相关推荐
RFCEO7 小时前
C语言逆向学习基础课 第7课 函数参数传递与返回值陷阱
c语言逆向学习基础课·c语言函数参数传递陷阱·c语言值传递与地址传递区别·c语言返回局部变量指针错误·c语言函数返回值校验·c语言堆内存分配与释放