Skip to content

[Bug] dfs_elm.c 中因 open/close 逻辑不一致导致的内存泄漏 #10847

@wdfk-prog

Description

@wdfk-prog

RT-Thread Version

Master

Hardware Type/Architectures

STM32F407

Develop Toolchain

RT-Thread Studio

Describe the bug

  • dfs/filesystems/elmfat/dfs_elm.c 文件中的 dfs_elm_opendfs_elm_close 函数在处理文件引用计数 (ref_count) 时的行为不一致,导致了严重的内存泄漏。

问题根源分析:

  1. dfs_elm_open 的行为: 无论一个文件被打开多少次 (ref_count 值是多少),dfs_elm_open 函数总是会为每一次 open 调用执行 rt_malloc 来分配一个新的底层文件句柄 (FILDIR 结构体)。
  2. dfs_elm_close 的行为:open 的行为相反,dfs_elm_close 函数在开始处包含一个检查 if (file->vnode->ref_count > 1)。如果这个条件成立(意味着还有其他文件描述符指向同一个文件),函数会直接返回,并不会调用 rt_free 来释放当初为这个文件描述符在 open 时所分配的内存。

导致的后果:
这种 open (总是分配) 和 close (有条件释放) 之间的逻辑不对称,导致对同一个文件进行多次打开后,除了最后一次关闭操作外,之前所有的关闭操作都会跳过资源释放步骤,造成与关闭次数成正比的内存泄漏。

Steps to reproduce the behavior (复现步骤)

  1. 分析代码发现,尚未测试
  2. 该部分逻辑与littlefs类似,littlefs处理不会导致malloc与free不一致问题,但是会导致第二次open失败

Expected behavior (预期行为)

每一次 close(fd) 调用都应该精确地释放与之对应的 open() 操作所分配的内存资源 (FILDIR 结构体)。在上述测试代码的循环中,initial_memfinal_mem 的值应该保持一致(不考虑系统其他任务的微小波动),不应出现累积性的内存增长。

Add screenshot / media if you have them (截图)

(无)

Other additional context

这个问题的根源在于 dfs_elm.c 文件中 dfs_elm_close 函数的以下代码块:

int dfs_elm_close(struct dfs_file *file)
{
    FRESULT result;

    RT_ASSERT(file->vnode->ref_count > 0);
    if (file->vnode->ref_count > 1)
    {
        return 0; // <--- 此处直接返回,导致内存泄漏
    }
    // ... 后续的释放逻辑 ...
}

建议的修复方案是直接移除这个 if (file->vnode->ref_count > 1) 判断,以确保 openclose 的资源管理行为是对称的。

另外,还有一个相关的逻辑不一致点:在 dfs_elm_open 函数中,对 ref_count 的检查仅在 FF_VOLUMES > 1 的宏条件下存在,而在单卷配置下则没有。虽然这不是导致内存泄漏的直接原因,但建议一并修复,以保证代码在不同配置下行为的统一性。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions