【缺陷周话】 第33期:错误的资源关闭
字数 1225 2025-08-18 11:38:32
错误的资源关闭缺陷分析与防范指南
1. 缺陷概述
错误的资源关闭(Improper Resource Shutdown or Release)是指程序员手动创建或申请的资源,在关闭时使用了不匹配的方法,而非创建或申请时对应的关闭函数。该缺陷被归类为CWE-404。
典型场景
- 使用
fopen()打开文件,却用_close()而非fclose()关闭 - 使用
freopen()、_open()、CreateFile()等函数打开资源后使用了不匹配的关闭方法
2. 危害分析
错误的资源关闭会导致:
- 非预期的程序行为
- 资源泄漏
- 程序崩溃风险
- 系统稳定性问题
3. 代码示例分析
3.1 缺陷代码示例
// CWE404_Improper_Resource_Shutdown__fopen_w32_close_01.c
void bad() {
FILE * data;
/* Initialize data */
data = NULL;
/* POTENTIAL FLAW: Open a file using fopen() */
data = fopen("file.txt", "w+");
if (data != NULL) {
/* FLAW: Attempt to close the file using close() instead of fclose() */
_close((int)data);
}
}
问题点:
- 第6行使用
fopen()打开文件 - 第9行错误地使用
_close()而非fclose()关闭文件
3.2 修复后代码
void good() {
FILE * data;
/* Initialize data */
data = NULL;
/* FIX: Open a file using fopen() */
data = fopen("file.txt", "w+");
if (data != NULL) {
/* FIX: Close the file using fclose() */
fclose(data);
}
}
修复要点:
- 保持资源打开与关闭方法的一致性
- 使用
fopen()对应的fclose()关闭文件
4. 检测方法
静态代码分析
使用专业源代码安全检测工具(如代码卫士)可以:
- 自动识别资源打开与关闭的不匹配情况
- 标记缺陷位置并评估风险等级(通常为高风险)
检测特征:
- 资源获取函数与释放函数的配对检查
- 跨函数调用的资源生命周期追踪
5. 防范措施
5.1 开发实践
-
严格配对原则:每个资源获取函数必须使用其对应的释放函数
fopen()↔fclose()_open()↔_close()CreateFile()↔CloseHandle()
-
资源管理规范:
- 建立资源获取/释放的编码规范
- 对复杂资源生命周期进行文档说明
-
代码审查:
- 将资源管理作为代码审查的重点项
- 特别关注跨函数/模块的资源传递
5.2 工具辅助
- 使用静态分析工具进行自动化检测
- 集成到CI/CD流程中实现早期发现
- 利用IDE插件进行实时提示
5.3 设计模式建议
-
RAII模式(资源获取即初始化):
- 将资源生命周期与对象生命周期绑定
- 利用析构函数自动释放资源
-
智能指针(C++):
- 使用
std::unique_ptr、std::shared_ptr管理资源 - 自定义删除器处理特殊资源
- 使用
6. 扩展知识
相关CWE条目
- CWE-404:不正确的资源关闭或释放
- CWE-415:双重释放
- CWE-416:释放后使用
跨语言注意事项
不同编程语言中资源管理的差异:
- C/C++:需要显式管理,风险最高
- Java:垃圾回收机制,但需要关注非内存资源(如文件句柄)
- Python:上下文管理器(
with语句)是推荐做法 - Go:
defer语句确保资源释放
7. 总结
错误的资源关闭是常见的编程缺陷,可能导致严重的系统问题。通过:
- 严格遵守资源获取/释放的配对原则
- 采用良好的编程实践和设计模式
- 利用自动化工具进行检测
可以有效预防此类问题,提高代码质量和系统稳定性。