文档中的代码均为 C/C++内存操作错误 的典型案例,覆盖 内存泄漏、释放后使用(UAF)、双重释放、空指针解引用、置空无效 等核心问题,按错误类型+代码分析+问题根源拆解如下,同时补充修复思路,便于理解问题本质:
一、内存申请释放不匹配
1 | void Test(){ |
问题:自定义内存管理模块的内存,需通过 模块自身接口 释放,直接调用 free 会破坏内存池管理规则,导致内存池状态异常、后续申请/释放出错。
修复:替换为 内存管理模块 的释放接口,如 MemoryManagerFree(p)。
二、释放后使用(UAF)+ 全局指针未置空
1 | A*g; // 全局指针 |
问题:局部指针释放后仅置空 自身,全局指针仍指向 已释放 的内存区域,后续 Test2 解引用 g 触发释放后使用漏洞,属于严重的 时间内存问题。
修复:释放局部指针时,同步置空全局指针 g=NULL;。
三、内存泄漏(被调用方申请,调用方未释放)
1 | void TestHandle(void **p){ *p=malloc; } // 被调用方申请内存 |
问题:子函数通过二级指针为父函数的指针分配内存,父函数未接管内存释放操作,函数结束后指针销毁,内存无引用可释放,造成 显性内存泄漏。
修复:调用方使用完后释放内存 free(p); p=NULL;。
四、指针置空操作无效(仅修改形参)
1 | void CustomFree2(int *p){ |
问题:C语言中函数参数为 值传递,此处仅修改形参 p 的地址,主调函数中的 实参指针 仍指向 已释放的内存,置空操作无实际防护效果,后续仍可能解引用非法指针。
修复:通过二级指针接收参数,修改实参指向:
1 | void CustomFree2(int **p){ |
五、条件分支导致的内存泄漏(指针重分配未释放原内存)
1 | void TestLocalRemalloc(int cond) { |
问题:
- 语法错误:cond=3 是 赋值 操作,非条件判断,导致该分支 恒成立;
- 内存泄漏:cond=3 分支中,直接为 p 分配新内存,未释放 原 malloc 的内存,原内存地址丢失,造成泄漏;
- 若修正为 cond==3,仍存在分支内的泄漏问题。
修复:
- 修正判断符: cond==3;
- 重分配前释放原内存: free(p); p = malloc(…);。
六、跨过程内存泄漏(分支提前return,未释放子函数申请的内存)
1 |
|
问题:data>0 分支中提前 return ,未释放子函数 CreateData 申请的 q 内存,属于 跨过程的内存泄漏,简单的字符串扫描无法识别(需追踪跨函数的内存持有关系)。
修复:提前返回前释放所有申请的内存 free(q); q=NULL; return;。
七、全局变量导致的双重释放风险
1 | int* p_mem; // 全局指针 |
问题:当 cond_code<0 时,局部指针 q 被释放 但 全局指针 p_mem 未置空,后续 UAFTestCase2Free 检测 p_mem!=NULL 并释放,触发 双重释放(DF);若 UAFTestCase2Free 是解引用而非释放,则触发 UAF。
修复:释放 q 时 同步置空 全局指针 p_mem=NULL; 。
八、结构体指针操作空指针解引用风险(多层嵌套结构体,未判空)
核心结构体定义
1 | typedef struct{ |
风险代码
1 |
|
核心问题
- 拼写错误:判空的是 psg (不存在的字段),而非实际的 pMsg, malloc 失败时 pMsg=NULL ,后续直接解引用触发空指针解引用;
- 多层嵌套结构体的指针字段( oMsg.data1.inner_data.pMsg )在所有操作前均未做判空校验;
- 全局结构体的指针字段被多个函数直接调用,一处 NULL 会导致所有调用函数崩溃。
修复
- 修正拼写错误: oMsg.data1.inner_data.pMsg==nullptr ;
- 所有使用 pMsg 的位置,先判空再操作: if(pMsg == NULL) return; ;
- 全局结构体指针赋值后,立即做判空防护。
所有程序的共性问题总结
1.指针管理失序:申请/释放/赋值未形成闭环,局部指针释放后未同步置空全局/关联指针;
2.分支/跨函数追踪缺失:条件分支提前return、子函数申请内存,未做全路径的释放处理;
3.语法/拼写错误: = 与 == 混淆、变量名拼写错误,导致内存操作逻辑失效;
4.值传递认知不足:直接修改函数形参指针,误以为能改变实参指向;
5.判空防护缺失:对动态分配的指针(尤其是结构体嵌套指针),未做前置判空。