簡體   English   中英

為什么在調用lseek之后讀取的文件總是返回0?

[英]Why does a file read after calling lseek always return 0?

我不明白為什么lseek之后的讀取調用返回0個讀取的字節數。

//A function to find the next note for a given userID;
//returns -1 if at the end of file is reached;
//otherwise, it returns the length of the found note.
int find_user_note(int fd, int user_uid) {
    int note_uid = -1;
    unsigned char byte;
    int length;

    while(note_uid != user_uid) { // Loop until a note for user_uid is found.
        if(read(fd, &note_uid, 4) != 4) // Read the uid data.
            return -1; // If 4 bytes aren't read, return end of file code.
        if(read(fd, &byte, 1) != 1) // Read the newline separator.
            return -1;

        byte = length = 0;
        while(byte != '\n') { // Figure out how many bytes to the end of line.
            if(read(fd, &byte, 1) != 1) // Read a single byte.
                return -1; // If byte isn't read, return end of file code.

            //printf("%x ", byte);
            length++;
        }
    }
    long cur_position = lseek(fd, length * -1, SEEK_CUR ); // Rewind file reading by length bytes.

    printf("cur_position: %i\n", cur_position);

    // this is debug
    byte = 0;
    int num_byte = read(fd, &byte, 1);

    printf("[DEBUG] found a %d byte note for user id %d\n", length, note_uid);
    return length;
}

當存在外部while循環時,變量長度值為34,上面的代碼產生cur_position 5(因此lseek函數返回后肯定至少有34個字節),但是從函數read返回的變量num_byte始終返回0,即使存在還有更多字節要讀取。

有人知道num_byte總是返回0的原因嗎? 如果我的代碼有誤,則看不到它是什么。

僅供參考,以上代碼在以下計算機上運行

$ uname -srvpio
Linux 3.2.0-24-generic #39-Ubuntu SMP Mon May 21 16:52:17 UTC 2012 x86_64 x86_64 GNU/Linux

更新:

  • 我在這里上傳完整的代碼
  • 這是我嘗試讀取的文件的內容
 $ sudo hexdump -C /var/notes 00000000 e8 03 00 00 0a 74 68 69 73 20 69 73 20 61 20 74 |.....this is at| 00000010 65 73 74 20 6f 66 20 6d 75 6c 74 69 75 73 65 72 |est of multiuser| 00000020 20 6e 6f 74 65 73 0a | notes.| 00000027 $ 

如果length是小於off_t的無符號類型(例如,在32位計算機上為size_t ),則length*-1將是一個巨大的值(大約4GB左右)。 這可能是問題所在。 lseek的結果存儲為long lseek (同樣,如果是32位),將應用實現定義的轉換(可能是截斷),從而再次給您帶來較小的價值。

我看到您的機器是64位的,但是也許您正在運行32位的用戶空間?

無論如何,為什么不在strace下運行程序以查看正在執行的系統呢? 這幾乎肯定可以很快解決問題。

我終於找到了問題!!! 我必須放入#include <unistd.h>才能使用正確的lseek()。 但是我不確定為什么不包含unistd.h會導致意外行為,但是它是可編譯的。 我認為如果不包括函數原型,它甚至不應該是可編譯的。

該代碼由喬恩·埃里克森(Jon Erickson)在《 黑客:剝削的藝術》第二版中編寫,我已經證實在書中沒有#include <unistd.h>

將初始可變長度設置為34時,以上代碼將產生cur_position 5(因此lseek函數返回后肯定至少有34個字節)

情況並非一定如此,因為人們可以在文件末尾查找,而不會出現任何錯誤。

請參見下面的lseek()手冊頁摘錄:

lseek()函數允許將文件偏移設置為超出文件末尾(但這不會更改文件的大小)。

因此,很可能從lseek() ing接收值,該值仍然指向文件末尾。 因此從該位置開始的read()仍將返回0(因為超出文件末尾)。


我也同意R ..的觀點,在使用正確的類型(所使用的方法所使用的類型)時要多加小心,這不是一個壞主意。


更新 :此外,您可能還要注意包括所調用系統函數的所有標頭。 為了檢查這種情況,我強烈建議使用gcc-Wall選項打開所有編譯器警告,它們是免費的... ;-)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM