在使用 fmemopen 打开的 FILE* 上使用 rewind()

Using rewind() on a FILE* opened with fmemopen

已通过 glibc 2.24 解决——请参阅下面的更新

这是一段 C 代码(使用 gcc 5.3.1、glibc 2.23 编译):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

int main() {
  const char* s1="Original content of file.\n"
                 "still original content and some remaining original content.\n";
  const char* s2="overwriting data  with new content\n";
  const char* s3="appended data\n";

  const size_t bufsz=strlen(s1)+1;
  char buf[bufsz];
  FILE *f;
  int r;

  f=fmemopen(buf,bufsz,"w");
  assert(f!=NULL);

  // setbuf(f, NULL);          // variant no. 1
  // setbuffer(f, buf, bufsz); // variant no. 2

  r=fwrite(s1,strlen(s1),1,f);
  assert(r==1);

  r=fflush(f);
  assert(r==0);

  rewind(f);

  r=fwrite(s2,strlen(s2),1,f);
  assert(r==1);

  r=fwrite(s3,strlen(s3),1,f);
  assert(r==1);

  r=fclose(f);
  assert(r==0);

  printf("%s",buf);
}

怎么了?我做错了吗?或者这是一个 GLIBC 错误?

更新

8月4日,新的glibc 2.24版本发布。使用 gcc 5.4.0 和 glibc 2.24,变体号。 1(无缓冲文件)工作正常。变体 2(自缓冲版本)给出了不同但仍然错误的结果。因此,我相信 R.. 声称这是联机帮助页 fmemopen(3) 中的文档错误是正确的。我会提出错误报告 ...

Now, the manpage fmemopen(3) advices to either disable buffering (uncomment variant 1), or to explicitely set buf as buffer (uncomment variant 2).

后者肯定是未定义的行为。不要这样做。我不清楚您在 Linux 手册页中找到的文本:

Alternatively, the caller can explicitly set buf as the stdio stream buffer, at the same time informing stdio of the buffer's size, using:

setbuffer(stream, buf, size);

正在尝试表达,但这是一个文档错误,可能应该被删除。

至于无缓冲模式不工作,这可能是一个 glibc 错误。尝试尽可能减少测试用例,针对最近的 glibc 进行测试,如果仍然发生,请在 glibc bugzilla 上提交错误报告:

https://sourceware.org/bugzilla/enter_bug.cgi?product=glibc

当您想立即了解错误时,一个安全的替代方法是调用 fflush 并检查 return 值。