任何人都可以在內存流中解釋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