在閱讀不同專案的源代碼時,我已經多次看到這種編碼模式。
z = read(fd, buf, sizeof(buf));
buf[z] = 0;
據我所知,這是為了確保 c 風格的字串被空位元組正確終止。但這是一種好的編碼風格嗎?看起來可能存在可能損壞其他資料的越界寫入。
uj5u.com熱心網友回復:
buf必須足夠大以容納資料加上空終止符。正確的方法是讀取sizeof(buf)-1(假設buf是 type char[])位元組到buf.
buf[sizeof(buf)]將在最后分配的成員之后訪問記憶體,并且由于 C 陣列的索引為 0 而無效。
回傳read的數字是讀取的位元組數,或者-1如果read失敗,請務必檢查這種可能性。
讀取的位元組數對應于buf未讀取的第一個位元組的索引。
正確代碼:
z = read(fd, buf, sizeof(buf)-1);
if (z == -1) {
// Handle error
} else {
buf[z] = 0;
}
uj5u.com熱心網友回復:
據我所知,這是為了確保 c 風格的字串被空位元組正確終止。
是的,這似乎是最有可能的目的。當然,這僅在想要將資料解釋為字串時才有用。這并不少見,但絕不是普遍的。
但這是一種好的編碼風格嗎?看起來可能存在可能損壞其他資料的越界寫入。
你是對的。如果read()傳輸的最大位元組數,并假設它buf被定義為一個陣列,而不是一個指標*,那么
buf[z] = 0;
將對 array 執行越界訪問buf。如果希望在讀取后能夠以buf字串的形式訪問 的內容,而不會丟失任何資料,則必須為終止符保留一個字符:
z = read(fd, buf, sizeof(buf) - 1);
沒有以這種方式顯式保留至少一個字符的代碼隱含地假定它永遠不會看到最大長度的讀取。在某些情況下,這可能是一個相對安全的假設,但我不想對此表示懷疑。
此外,如果read()失敗則回傳-1。在這種情況下,to 的分配buf[z]也將超出范圍。必須通過read()在使用它之前檢查它的回傳值來避免這種情況,因為幾乎總是應該對可能以這種方式指示錯誤條件的函式呼叫的回傳值進行處理。
*如果buf是指標而不是陣列,則存在完全不同的問題:sizeof(buf)報告指標的大小,而不是指標指向的物件的大小。
uj5u.com熱心網友回復:
如果呼叫成功,該read函式回傳寫入的位元組數。buf如果發生錯誤,則回傳值為 -1。
因此,在結束之后buf和開始之前都可能出現越界寫入buf。
一種處理方法是:
z = read(fd, buf, sizeof(buf) - 1);
if(z >= 0) {
buf[z] = 0;
} else {
/* handle error */
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/507331.html
標籤:C
上一篇:如何使用printf顯示具有常規大小并填充其他字符而不是空格的字串?
下一篇:寫入malloc字串
