任何人都可以在内存流中解释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=%d\n",written);
int fstatus = fflush(file);
fprintf(stderr,"fstatus=%d\n",fstatus);
long ftellpos = ftell(file);
fprintf(stderr,"ftellpos=%ld\n",ftellpos);
fstatus = fseek(file, 0, SEEK_END);
fprintf(stderr,"fstatus=%d\n",fstatus);
ftellpos = ftell(file);
fprintf(stderr,"ftellpos2=%ld\n",ftellpos);
return 0;
}
上RHEL7的输出是:
2.17
written=4
fstatus=0
ftellpos=4
fstatus=0
ftellpos2=4
而在openSUSE飞跃器42的输出是:
2.22
written=4
fstatus=0
ftellpos=0
fstatus=0
ftellpos2=4
(这导致了单元测试失败代码我在看)
个我的问题是:
- 是必需的FSEEK()(由标准),使FTELL的()的结果是否有效?
- 这是glibc行为的错误还是更改?
- 为什么它不适用于OpenSUSE?
最明显的实现是用于文件位置指示器是 在给予fmemopen所述存储器缓冲区索引。它很难看出如何可能出错。
实际上实现:
https://github.com/bminor/glibc/blob/73dfd088936b9237599e4ab737c7ae2ea7d710e1/libio/fmemopen.c
具有C-> POS = POS + S;在线路85
想必FTELL()只返回C-> POS(以一种迂回的方式)
已经有glibc的源源的一些重新组织2.17和2.22 这可能可以解释之间这个如果我能解开它。 但它是一个错误或功能?
我不确定Posix和C标准是否完全指定fllll 应该对内存流正常工作。 直觉上很难看出为什么它不应该强制执行,因为它 应该只是工作。
说:
“的当前位置由隐式I/O操作更新 可以使用FSEEK明确地更新(3),以及使用FTELL(3)来确定的。”。
其他手册页提到,ftell可能不需要为非真正的文件工作 。 但是,我相信他们真的在那里有设备。
那么,关于**标准函数的唯一权威资源是什么告诉你的? – Olaf
听起来像一个错误 - [文件在这里](https://sourceware.org/bugzilla/enter_bug.cgi?product=glibc) – o11c
尽管不太可能出现这个问题,但在这里完成的随机整数类型转换为帖子添加了不必要的问题。建议使用正确的类型和打印说明符。 'ftell()'返回'long','size_t'需要''zu'''。 – chux