[英]getline() vs. fgets(): Control memory allocation
要從文件中讀取行,可以使用getline()
和fgets()
POSIX函數(忽略可怕的gets()
)。 常識是getline()
比fgets()
更fgets()
因為它根據需要分配行緩沖區。
我的問題是:這不危險嗎? 如果出於偶然或惡意的意圖,有人創建了一個沒有'\\n'
字節的100GB文件,那會不會讓我的getline()
調用分配一個瘋狂的內存量?
我的問題是:這不危險嗎? 如果出於偶然或惡意的意圖,有人創建了一個沒有'\\ n'字節的100GB文件,那會不會讓我的getline()調用分配一個瘋狂的內存量?
是的,你所描述的是一種看似合理的風險。 然而,
getline()
嘗試這樣做本身並不比使用fgets()
編寫自己的代碼更危險; 和 setrlimit()
限制其可以保留的(虛擬)內存總量來降低風險。 這可以用於使其失敗,而不是成功分配足夠的內存來干擾系統的其余部分。 我認為,最好的整體是編寫不需要以實線為單位輸入的代碼(一次全部),但這種方法有其自身的復雜性。
這可能很危險,是的。 不知道這在其他計算機上是如何工作的,但運行下面的代碼會凍結我的計算機到需要硬重置的程度:
/* DANGEROUS CODE */
#include <stdio.h>
int main(void)
{
FILE *f;
char *s;
size_t n = 0;
f = fopen("/dev/zero", "r");
getline(&s, &n, f);
return 0;
}
getline
函數在內部使用malloc
和realloc
,如果失敗則返回-1,因此結果與嘗試調用malloc(100000000000)
沒有區別。 即, errno
設置為ENOMEM
, getline
返回-1。
因此,無論您是使用getline
還是嘗試使用fgets
和手動內存分配執行相同的操作,您都會遇到同樣的問題,以確保您閱讀完整行。
某些編碼指南(如MISRA C)可能會阻止您使用動態內存分配(如getline()
)。 這是有原因的,例如避免內存泄漏。
如果您知道所有可接受行的最大大小,那么可以使用fgets()
而不是getline()
來避免內存分配,從而刪除一個潛在的內存泄漏點。
getline()
為您重新分配緩沖區,以減輕程序中的內存管理。
但實際上,這可能導致分配大量內存。 如果這是一個問題,那么您應該采取額外的步驟來使用不隱式分配內存的函數。
真的,這取決於你想要處理太長的行。
具有合適大小的緩沖區的fgets
通常會工作,並且您可以檢測到它已“失敗” - 緩沖區末端沒有換行符。 可以避免總是使用strlen()來確認緩沖區是否溢出,但這是一個不同的問題。
也許你的策略是簡單地跳過無法處理的行,或者行的其余部分只是你無論如何都會忽略的注釋,在這種情況下,很容易將fgets
放入循環中以丟棄其余的這條線沒有分配罰金。
如果您確實想要讀取整行,那么getline
對您來說可能是更好的策略。 惡意用戶需要大量磁盤空間才能導致您描述的不良行為,或者可能傳遞/ dev / random或類似輸入文件名。
同樣,如果getline
無法重新分配,它將以您可以恢復的方式失敗,但是如果您正在重復使用緩沖區進行多行讀取,則可能需要在嘗試讀取之前釋放它在錯誤之后具有的緩沖區更多,因為它仍然被分配,並且可能在失敗之前增長到盡可能大。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.