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

Labels

bugThis PR/issue is a bug in the current code.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions