[英]Segmentation fault as a result of using fgets() to read lines from a file into a struct array
我目前正在學習 C,需要一些代碼幫助。
假設有一個名為“books.txt”的文件,它在文件的新行中包含了幾本書的名稱。 我試圖獲取每本書的名稱以用於我程序的其余部分。
為此,我創建了以下內容:
struct bookData { // This is my struct to encapsulate book information
char name[50]; // Name of book
// Other struct variable
// Other struct variable
};
現在我需要獲取每本書的名稱並將它們放入一個結構數組中。 下面是我如何去做。
struct bookData booksList[numBooks]; // numBooks is the number of books in "books.txt"
int i;
for(i = 0; i < numBooks; i++) {
fgets(booksList[i].name, 50, books);
// Books is the "books.txt" file that was opened for reading
}
當我運行此代碼時,我遇到了分段錯誤。 我相信問題在於 for 循環的使用。 但是我不確定如何糾正這個問題,甚至不確定為什么循環會導致出現分段錯誤。 當我簡單地放置線時,
fgets(booksList[0].name, 50, books);
沒有 for 循環,不會發生錯誤,代碼運行並打印書名就好了。
我試圖了解為什么我的代碼中出現錯誤。 如果有人可以就如何修復錯誤給我建議,我將不勝感激。 預先感謝您花時間閱讀/回答我的問題!
編輯:numBooks 本質上是“books.txt”文件中的行數。 這轉化為這個特定問題的書籍數量。 numBooks 是用以下代碼計算的:
char c;
int numBooks;
while((c = fgetc(books)) != EOF) {
if(c == '\n') {
numBooks++;
}
}
編輯#2:謝謝大家的幫助!!!
以下代碼是錯誤的,可以合理地預期會導致問題:
char c;
int numBooks;
while((c = fgetc(books)) != EOF) {
if(c == '\n') {
numBooks++;
}
}
首先, numBooks
未初始化,以后使用它可能會調用未定義的行為。
其次,雖然在大多數系統上引起問題的可能性要小得多,但fgetc
返回int
,它通常具有更寬的域(可以表示比unsigned char
更多的值)。 這樣做是有原因的。 fgetc
返回的任何實際字符值都將作為unsigned char
(即僅正數)值。 失敗將導致EOF
(僅限負數)。 這意味着fgetc
通常可以返回 257 個值之一,並且通過直接轉換為char
您將丟棄這些值之一:錯誤處理值。 換句話說,您無法再判斷fgetc
成功。 當你到達EOF
時會發生什么? 您將其轉換為char
,將其視為字符值(如果不是),然后再試一次..? 錯誤的答案!
總之, fgetc
返回int
,因此將返回值存儲在int
...
當numBooks
達到INT_MAX
和numBooks++;
時會出現另一個問題numBooks++;
會導致溢出。 從技術上講,這是未定義的行為,理論上可能會導致分段錯誤……但我從未親自見過。 盡管如此,您可能應該使用unsigned
類型,因為文件中的條目數為負數是沒有意義的,是嗎?
細想一下,如果numBooks
在struct bookData booksList[numBooks];
為負數(或足夠大的數字),當您訪問更高的元素時,您可能會開始看到分段違規。
總結:當您只希望看到正數時使用無符號類型,並為大數組使用動態分配(例如malloc
)。
請注意,這並未涵蓋所有可能性,因為您尚未提供MCVE,因此這樣做是不可能/不切實際的; 您的段錯誤很可能是由您未提供的其他代碼引起的。 如果您更新此問題,請告訴我,以便我可以更新此答案並讓世界保持旋轉:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.