[英]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, ¬e_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.