[英]How come my C program doesn't crash when I overflow an allocated array of characters?
我有一個簡單的C文件I / O程序,它演示了逐行讀取文本文件,並將其內容輸出到控制台:
/**
* simple C program demonstrating how
* to read an entire text file
*/
#include <stdio.h>
#include <stdlib.h>
#define FILENAME "ohai.txt"
int main(void)
{
// open a file for reading
FILE* fp = fopen(FILENAME, "r");
// check for successful open
if(fp == NULL)
{
printf("couldn't open %s\n", FILENAME);
return 1;
}
// size of each line
char output[256];
// read from the file
while(fgets(output, sizeof(output), fp) != NULL)
printf("%s", output);
// report the error if we didn't reach the end of file
if(!feof(fp))
{
printf("Couldn't read entire file\n");
fclose(fp);
return 1;
}
// close the file
fclose(fp);
return 0;
}
看起來我已經為每行分配了一個空間為256個字符的數組(32位機器上的1024
字節
位)。 即使我在第一行填寫的文本超過1000個字符的ohai.txt
,程序也不會出現段錯誤,我認為它會溢出,因為它溢出了output[]
數組指定的可用空間。 。
我的假設是操作系統會為程序提供額外的內存,同時它有額外的內存可用。 這意味着只有當ohai.txt
的一行文本占用的內存導致ohai.txt
時,程序才會崩潰。
有更多C和內存管理經驗的人是否支持或反駁我的假設,即為什么這個程序不會崩潰,即使文本文件的一行中的字符數遠大於256?
你不會在這里溢出任何內容: fgets
不會向sizeof(output)
字符寫入緩沖區,因此不會溢出任何內容(參見文檔 )。
但是,如果溢出緩沖區,則會出現未定義的行為。 根據C規范,程序可能會做任何事情 :崩潰,不崩潰,無聲地破壞重要數據,意外調用rm -rf /
等等。因此,如果調用UB,不要指望程序崩潰。
OP的程序沒有崩潰,因為沒有緩沖區溢出發生。
while(fgets(output, sizeof(output), fp) != NULL)
printf("%s", output);
fgets()
很好地讀取一組char
到一個或255或一個\\n
的計數。 然后printf("%s" ...
很好地將它們打印出來。重復這一過程,直到沒有更多的數據/
沒有崩潰,沒有溢出,沒有運行,沒有命中,沒有錯誤。
fgets(output,sizeof(output),fp)讀取(sizeof(輸出)-1)這種情況下的字符數(否則讀取直到換行符或文件末尾)
堆棧的解釋以及為什么即使你實際上溢出也不會發生段錯誤(並且正如其他人已指出所寫的代碼不會)
你的堆棧指針從某個地址開始,比如說0x8000000,然后運行時調用main,它會向下移動一點(可能還有其他的東西,所以我們不知道在main的開頭有多少東西在堆棧上),然后main將為所有它的局部變量移動堆棧指針。 所以在這一點上你的數組將有一個低於0x8000000超過256字節的地址,除非你在所有main的堆棧幀和任何其他C運行時東西的堆棧幀上運行,否則你不會得到段錯誤。
因此,為了簡單起見,假設您的數組最終得到的是0x7fffd00的基地址,即低於0x8000000的768字節,這意味着至少你必須溢出那么多以獲得段錯誤(好吧,你可能會遇到段錯誤)主要返回或當你調用feof時,因為你用隨機字符填充你的堆棧框架,但是我們正在討論fgets()中的段錯誤,但即使那些可寫的東西被映射到堆棧上方的頁面也是如此(不太可能是大多數操作系統)避免這樣做,這樣如果你溢出得足夠遠,你會得到一個段錯誤)
如果堆棧以另一種方式運行(即:向上增長),則必須運行整個最大大小的堆棧,在用戶空間中通常非常大(Linux上的默認值為32位x86是2MB)但我很漂亮確保x86堆棧向下增長,這樣你的情況就不太可能了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.