C - 'correct' 在内存流上使用时 ftell() 的语义



任何人都可以解释在内存流上使用时ftell()的'正确'语义。

给定以下程序:

#include <stdio.h>
#include <stdlib.h>
#include <gnu/libc-version.h>
int main(void)
{
   puts (gnu_get_libc_version ());
   size_t n_buffer = 1024;
   char *buffer = calloc(n_buffer, sizeof(char));
   FILE *file = fmemopen(buffer, n_buffer, "w");
   /* "ABCD" */
   static const char magic_number[] = 
   {
     0x41, 0x42, 0x43, 0x44 
   };
   const size_t written = fwrite(magic_number, 1, 4, file);
   fprintf(stderr,"written=%dn",written);
   int fstatus = fflush(file);
   fprintf(stderr,"fstatus=%dn",fstatus);
   long ftellpos = ftell(file);
   fprintf(stderr,"ftellpos=%ldn",ftellpos);
   fstatus = fseek(file, 0, SEEK_END);
   fprintf(stderr,"fstatus=%dn",fstatus);
   ftellpos = ftell(file);
   fprintf(stderr,"ftellpos2=%ldn",ftellpos);
   return 0;
}

RHEL7上的输出为:

2.17
written=4
fstatus=0
ftellpos=4
fstatus=0
ftellpos2=4

opensuse leap 42的输出为:

2.22
written=4
fstatus=0
ftellpos=0
fstatus=0
ftellpos2=4

(这导致我正在查看的代码中的单位测试失败)

我的问题是:

  • (按标准)需要FSEEK()才能使FTELL()有效吗?
  • 这是glibc的行为的错误还是变化?
  • 为什么它不适用于OpenSuse?

最明显的实现是文件位置指标为给予FMemopen的内存缓冲区中的索引。很难看到这怎么可能出错。

确实是实现:

https://github.com/bminor/glibc/blob/73dfd088936b92375999e4ab737c7ae2ea7d710e1/libio/fmemopen.c

具有c-> pos = pos s;在第85行。

大概是ftell()只是返回c-> pos(以回旋方式)

在2.17和2.22之间,GLIBC源已经重新组织了一定如果我能拆开它,那可能会解释这一点。但是它是错误还是功能?

我不确定POSIX和C标准是否完全指定FTELL是否完全指定应该对内存流正确工作。直觉上很难理解为什么不应该这样做应该只是工作。

http://man7.org/linux/man-pages/man3/fmemopen.3.html

说:

"当前位置由I/O操作隐含更新。可以使用FSEEK(3)明确更新,并使用FTELL(3)确定。"

其他男子页面提到,Ftell可能不必工作对于不是真正文件的东西。但是,我相信他们确实在牢记那里。

刚刚在讨论中的网络上找到了这句话:

ftell()开放组基本规格问题7 doc states'ftell()应返回流的文件位置指示器的当前值。'如果没有中间调用的文件位置指示器将不会更新FFLUSH功能或文件定位功能(FSEEK,FSETPOS或REWIND),或直到缓冲区已满。

因此,看起来RH和SUSE有一些缓冲处理差异。您需要以一种读取文件中正确位置的方式冲洗缓冲区。

相关内容

  • 没有找到相关文章

最新更新