You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用fmemopen创建的内存文件写入后无内容,求问题排查

问题:使用fmemopen合并文件后读取始终得到EOF

需求:读取磁盘多个文件合并,不想创建临时文件,用fmemopen在内存中通过FILE API操作,已有单个文件处理代码。核心代码如下(省略错误检查):

#define MODE_APPEND "a"

int main(int argc, char *argv[]) {    
  off_t concatenated_file_size = 0;
  for (int i = 1; i < argc; i++) {
    concatenated_file_size += get_file_size(argv[i]);
  }

  char *buf = nullptr;
  FILE *concatenated_file = fmemopen(buf, concatenated_file_size, MODE_APPEND);

  for (int i = 1; i < argc; i++) {
    FILE *file_to_concat = open_file(argv[i]);
    int c;
    while ((c = fgetc(file_to_concat)) != EOF) {
      fputc(c, concatenated_file);
    }
  }
  rewind(concatenated_file);
  int prevchar = fgetc(concatenated_file);
}

其中get_file_size通过stat实现,open_file是带错误检查的fopen,均测试正常。但prevchar始终为EOF,写入内容未保存到fmemopen返回的FILE*中,请问是API特性还是代码有误?


原因与修正方案

你的代码存在两处关键错误,并非fmemopen的API特性问题:

1. 空指针buf与追加模式的冲突

当buf传入nullptr时,fmemopen会自动分配一块大小为concatenated_file_size的内存,但你使用的"a"(追加模式)会让文件指针初始指向内存块的末尾。此时写入内容会直接超出内存块的有效范围,触发未定义行为,实际没有任何内容被写入到有效内存区域,后续自然读取到EOF。

2. 追加模式的使用场景错误

"a"模式设计用于磁盘文件的追加写入,但fmemopen的内存块是固定大小的。你计算的总大小刚好是内存块的容量,初始指针在末尾后,没有剩余空间容纳写入的内容,直接导致写入失败(或越界)。

修正后的核心代码

#define MODE_RW "w+"  // 改用读写模式,初始指针指向内存块开头,支持读写操作

int main(int argc, char *argv[]) {    
  off_t concatenated_file_size = 0;
  for (int i = 1; i < argc; i++) {
    concatenated_file_size += get_file_size(argv[i]);
  }

  // 手动分配内存,方便后续直接访问合并后的内容(也可传NULL让fmemopen自动分配)
  char *buf = malloc(concatenated_file_size);
  if (!buf) {
    // 此处添加错误处理逻辑
  }

  FILE *concatenated_file = fmemopen(buf, concatenated_file_size, MODE_RW);

  for (int i = 1; i < argc; i++) {
    FILE *file_to_concat = open_file(argv[i]);
    int c;
    while ((c = fgetc(file_to_concat)) != EOF) {
      fputc(c, concatenated_file);
    }
    fclose(file_to_concat);  // 关闭文件避免资源泄漏
  }

  rewind(concatenated_file);
  int prevchar = fgetc(concatenated_file);  // 此时可正确读取第一个字符

  // 后续处理合并后的内容...

  fclose(concatenated_file);
  free(buf);  // 释放手动分配的内存
}

额外注意事项

  • 如果让fmemopen自动分配内存(buf传NULL),后续无法直接通过buf访问内容,需借助fread等API读取;手动分配内存则可直接操作buf指针
  • 所有打开的FILE*必须调用fclose关闭,防止文件描述符泄漏
  • 写入完成后,除了rewind,也可以用fseek(concatenated_file, 0, SEEK_SET)将指针移到开头进行读取

内容的提问来源于stack exchange,提问作者Nate

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 15:31:09