2017-09-14 41 views
3

任何人都可以在內存流中解釋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可能不需要爲非真正的文件工作 。 但是,我相信他們真的在那裏有設備。

+0

那麼,關於**標準函數的唯一權威資源是什麼告訴你的? – Olaf

+0

聽起來像一個錯誤 - [文件在這裏](https://sourceware.org/bugzilla/enter_bug.cgi?product=glibc) – o11c

+1

儘管不太可能出現這個問題,但在這裏完成的隨機整數類型轉換爲帖子添加了不必要的問題。建議使用正確的類型和打印說明符。 'ftell()'返回'long','size_t'需要''zu'''。 – chux

回答

0

剛剛發現在網絡上這句話的討論:

的FTELL()公開組基本規範問題7個DOC國FTELL()應流返回文件位置指示器的當前值。'文件位置指示器不會在沒有對fflush函數或文件定位函數(fseek,fsetpos或rewind)的插入調用的情況下更新,或者直到緩衝區已滿。

因此,它看起來像rh和suse有一些緩衝區處理差異。您需要刷新緩衝區以讀取文件中的正確位置。

+0

我很清楚這一要求。請注意,在我的原始示例中寫入後有一個fflush調用。 –

+0

「我在泥土中發現了這個地方」並不是一個好的開始。如果允許或不允許,它不會回答(它是)。 – Olaf

+0

@Olaf是的,我知道,但它指向一個文檔並解釋行爲。 – Serge