首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C 語言除錯:Segment Fault (core dumped) 於大型檔案處理時發生

     編輯:程式設計綜合問答

問題背景

在撰寫 C 語言程式處理文字檔案時,發現一個詭異的段錯誤。程式包含兩個主要函數 next() 與 state_init()。當輸入檔案較小(不足 1000 行)時運行正常,但一旦檔案行數達到 900 行左右,程式便在第二個 while 迴圈的 fgetc() 呼叫處觸發 Segment fault: core dumped。更令人困惑的是:使用 GDB 除錯時,有時又能正常通過,只有行數更多時 GDB 也會報錯。

程式碼片段

void next(char c, int *row, int *col)
{
    if (c == '\t')
        *col = (*col + TABLEN - 1) / TABLEN * TABLEN + 1;
    else if (c == '\n') {
        cur_state.line_endpos[*row] = *col;
        *col = 1;
        (*row)++;
    } else
        (*col)++;

    if (*col > cur_state.win_width) {
        cur_state.line_endpos[*row] = *col - 1;
        *col -= cur_state.win_width;
        (*row)++;
    }
}

void state_init()
{
    char word;
    int cur_row, cur_col;
    cur_row = 1; cur_col = 1;
    fseek(FP, 0, SEEK_SET);
    ioctl(STDIN_FILENO, TIOCGWINSZ, &win);
    cur_state.win_height = win.ws_row;
    cur_state.win_width = win.ws_col;
    while ((word = fgetc(FP)) != EOF)
        next(word, &cur_row, &cur_col);
    cur_state.total_line = cur_row - 1;
    memset(&inbuffer, 0, sizeof(inbuffer));
}

可能原因分析

  1. 陣列越界:cur_state.line_endpos 可能是固定大小陣列,當 *row 超過其容量時寫入越界,導致堆疊損壞。GDB 可能改變記憶體佈局,使錯誤延後或掩蓋。
  2. 未初始化的指標/變數:FP、cur_state 或 win 若未正確初始化,行為將不可預測。
  3. 緩衝區溢位:inbuffer 大小若不足,memset 可能破壞相鄰記憶體。
  4. 檔案指標狀態:fseek 後若檔案開啟模式不當,fgetc 可能讀取失敗。

除錯建議

  • 檢查 cur_state.line_endpos 的定義與最大行數限制,確保動態分配或足夠大小。
  • 在 next() 入口加入斷言:assert(*row < MAX_LINES);。
  • 使用 valgrind 或 AddressSanitizer (-fsanitize=address) 偵測記憶體錯誤。
  • 將 word 宣告為 int 以正確比較 EOF。
  • 確認 FP 以 "r" 或 "rb" 正確開啟,且 fseek 成功。

結語

段錯誤在大檔案才出現,通常指向資料結構容量不足或索引計算邏輯隨資料增長而越界。建議先從陣列邊界檢查著手,輔以記憶體檢測工具,即可定位根因。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved