防护三件套:定义即初始化(NULL)+ free 后置 NULL + 边界检查。
一句话:"没定、失效、越界 = 野;初始化、置空、查界 = 防。"
野指针 = 指向"不确定/已失效/越界"内存的指针。解引用它 = 读垃圾值,或访问非法地址(段错误 / 嵌入式 HardFault 复位)。嵌入式裸机无 MMU 隔离,野指针直接打穿整个固件。
int *p; 后直接 *p = 5; → 往随机地址写。防:定义时初始化 int *p = NULL; 或 = &某变量int *p = malloc(10); free(p); *p = 5; → 指向已归还的内存。防:free 后立刻 p = NULL。另一变体:int *f(){ int x = 5; return &x; } 返回栈变量地址,函数返回后失效int a[10]; int *p = a; p[10] = 5; → 走到数组外。防:边界检查| 类型 | 成因 | 例子 | 防 |
|---|---|---|---|
| 未初始化 | 声明没赋初值 | int *p; *p = 5; |
定义即初始化/NULL |
| 悬垂 | 指向已释放/失效内存 | free(p) 后还用;返回栈地址 |
free 后置 NULL |
| 越界 | 走出数组/分配范围 | p[10](数组只有 10 个) |
边界检查 |
int *f() { int arr[5]; return arr; } → 悬垂(返回局部数组地址,栈销毁后失效)int g = 5; 后 int *p = &g; → 不是野指针(全局变量活整个程序期)int *p = NULL; *p = 1; → 不是野指针,是 NULL 解引用——NULL 是可控的空,野指针是失控的指| 相邻概念 | 和本主题的关系 | 孤立理解会犯的错 |
|---|---|---|
| 内存泄漏 | 悬垂 = 用了已释放的;泄漏 = 该释放没释放。一多一少 | 把两者混为一谈 |
| NULL | NULL 是"可控的空"(显式初始化),野指针是"失控的指" | 以为 NULL 就是野指针 |
| 堆 vs 栈 | 悬垂多发生在堆(free 后)和栈(返回局部地址) | 以为野指针只和堆有关 |
| HardFault / MMU | 嵌入式野指针归宿 = 总线错误 → HardFault → 复位;MMU 只在带虚拟内存的系统(如 Linux)存在 | 以为野指针只是"值不对",忽视崩溃后果 |
2026-08-03
每主题一页,复习时只翻本目录。