【缺陷周话】第31期:错误的内存释放
字数 1615 2025-08-18 11:38:28

错误的内存释放方法 - 代码安全缺陷详解

1. 错误的内存释放方法概述

在C/C++编程中,内存管理是一个核心且容易出错的部分。错误的内存释放方法指的是内存申请和释放方式不匹配的情况,主要包括:

  • C语言中:使用malloc()/calloc()/realloc()申请但用delete释放
  • C++中:使用new申请但用free()释放
  • C++中:使用new[]申请但用delete释放(或相反)

这种不匹配会导致未定义行为,可能引发内存泄漏、程序崩溃或更严重的安全问题。

2. 危害分析

错误的内存释放方法可能导致:

  1. 内存泄漏:部分内存无法被正确释放
  2. 堆损坏:破坏堆管理数据结构
  3. 程序崩溃:立即或延迟性的程序异常终止
  4. 安全漏洞:可能被利用进行攻击

根据《Effective C++(第二版)》条目5指出:"如果错误地释放对象中的元素,可能造成整个对象、甚至整个堆上的内存结构都发生损坏"。

3. 实际漏洞案例

2018-2019年CVE中记录的相关漏洞:

CVE编号 受影响软件 问题描述
CVE-2018-14948 dilawar sound(2017-11-27及之前版本) wav-file.cc文件中存在new[]/delete不匹配
CVE-2018-14947 PDF2JSON 0.69 XmlFonts.cc文件中XmlFontAccu::CSStyle函数存在new[]/delete不匹配
CVE-2018-14946 PDF2JSON 0.69 ImgOutputDev.cc文件中HtmlString类存在malloc/delete不匹配

4. 示例代码分析

4.1 缺陷代码示例

// 源自Samate Juliet Test Suite for C/C++ v1.3
// 文件名: CWE762_Mismatched_Memory_Management_Routines__new_array_delete_char_01.cpp

void bad()
{
    char * data;
    /* 使用new[]分配内存 */
    data = new char[100];
    /* 错误: 使用delete而非delete[]释放 */
    delete data;
}

问题分析

  • 第5行使用new[]分配了字符数组
  • 第7行错误地使用delete而非delete[]释放
  • 这种不匹配会导致未定义行为

4.2 修复代码

void good()
{
    char * data;
    /* 使用new[]分配内存 */
    data = new char[100];
    /* 正确: 使用匹配的delete[]释放 */
    delete [] data;
}

修复要点

  • 保持分配(new[])和释放(delete[])方法一致
  • 使用正确的数组释放语法

5. 检测方法

使用静态代码分析工具可以有效地检测这类问题:

  1. 代码卫士检测结果

    • 缺陷代码:检测出"错误的内存释放方法",等级为"中"
    • 修复代码:不再报告该缺陷
  2. 人工检查要点

    • 检查所有内存分配点
    • 跟踪对应的释放操作
    • 验证分配和释放方法是否匹配

6. 最佳实践建议

为避免错误的内存释放方法,建议:

  1. 编码规范

    • 明确团队的内存管理规范
    • 对每个new/new[]立即编写对应的delete/delete[]
  2. 代码审查

    • 将内存分配/释放匹配性作为代码审查重点
    • 特别关注跨函数/跨文件的内存管理
  3. 工具辅助

    • 使用静态分析工具进行自动化检测
    • 在CI/CD流程中加入内存检查环节
  4. 现代C++实践

    • 优先使用智能指针(unique_ptr, shared_ptr)
    • 使用容器类而非裸指针管理数组
    • 尽量减少显式的new/delete操作

7. 扩展知识

  1. 内存管理函数对应关系

    分配函数 释放函数
    malloc/calloc/realloc free
    new delete
    new[] delete[]
  2. 底层机制差异

    • new/delete会调用构造函数/析构函数
    • new[]会存储数组大小信息供delete[]使用
    • 混用会导致内存布局解释错误
  3. 跨语言问题

    • 避免在C++中使用C的内存管理函数
    • 模块接口处明确内存管理责任

通过遵循这些原则和实践,可以显著减少因内存释放方法错误导致的问题,提高代码的健壮性和安全性。

错误的内存释放方法 - 代码安全缺陷详解 1. 错误的内存释放方法概述 在C/C++编程中,内存管理是一个核心且容易出错的部分。错误的内存释放方法指的是内存申请和释放方式不匹配的情况,主要包括: C语言中:使用 malloc() / calloc() / realloc() 申请但用 delete 释放 C++中:使用 new 申请但用 free() 释放 C++中:使用 new[] 申请但用 delete 释放(或相反) 这种不匹配会导致未定义行为,可能引发内存泄漏、程序崩溃或更严重的安全问题。 2. 危害分析 错误的内存释放方法可能导致: 内存泄漏 :部分内存无法被正确释放 堆损坏 :破坏堆管理数据结构 程序崩溃 :立即或延迟性的程序异常终止 安全漏洞 :可能被利用进行攻击 根据《Effective C++(第二版)》条目5指出:"如果错误地释放对象中的元素,可能造成整个对象、甚至整个堆上的内存结构都发生损坏"。 3. 实际漏洞案例 2018-2019年CVE中记录的相关漏洞: | CVE编号 | 受影响软件 | 问题描述 | |---------|------------|----------| | CVE-2018-14948 | dilawar sound(2017-11-27及之前版本) | wav-file.cc文件中存在 new[]/delete 不匹配 | | CVE-2018-14947 | PDF2JSON 0.69 | XmlFonts.cc文件中 XmlFontAccu::CSStyle 函数存在 new[]/delete 不匹配 | | CVE-2018-14946 | PDF2JSON 0.69 | ImgOutputDev.cc文件中HtmlString类存在 malloc/delete 不匹配 | 4. 示例代码分析 4.1 缺陷代码示例 问题分析 : 第5行使用 new[] 分配了字符数组 第7行错误地使用 delete 而非 delete[] 释放 这种不匹配会导致未定义行为 4.2 修复代码 修复要点 : 保持分配( new[] )和释放( delete[] )方法一致 使用正确的数组释放语法 5. 检测方法 使用静态代码分析工具可以有效地检测这类问题: 代码卫士检测结果 : 缺陷代码:检测出"错误的内存释放方法",等级为"中" 修复代码:不再报告该缺陷 人工检查要点 : 检查所有内存分配点 跟踪对应的释放操作 验证分配和释放方法是否匹配 6. 最佳实践建议 为避免错误的内存释放方法,建议: 编码规范 : 明确团队的内存管理规范 对每个 new / new[] 立即编写对应的 delete / delete[] 代码审查 : 将内存分配/释放匹配性作为代码审查重点 特别关注跨函数/跨文件的内存管理 工具辅助 : 使用静态分析工具进行自动化检测 在CI/CD流程中加入内存检查环节 现代C++实践 : 优先使用智能指针( unique_ptr , shared_ptr ) 使用容器类而非裸指针管理数组 尽量减少显式的 new / delete 操作 7. 扩展知识 内存管理函数对应关系 : | 分配函数 | 释放函数 | |----------|----------| | malloc/calloc/realloc | free | | new | delete | | new[] | delete[ ] | 底层机制差异 : new / delete 会调用构造函数/析构函数 new[] 会存储数组大小信息供 delete[] 使用 混用会导致内存布局解释错误 跨语言问题 : 避免在C++中使用C的内存管理函数 模块接口处明确内存管理责任 通过遵循这些原则和实践,可以显著减少因内存释放方法错误导致的问题,提高代码的健壮性和安全性。