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

C 語言 read_line 函數緩衝區溢出風險:動態擴容才是正解

     編輯:程式設計綜合問答

原代碼 read_line(char str[], int n) 存在嚴重缺陷:當輸入字符超過 n 時,循環雖停止寫入,但 str[i] = '\0' 仍在固定大小棧數組內操作,若調用者傳入的數組小於實際輸入長度,會導致棧溢出、未定義行為。

問題代碼分析

int read_line(char str[], int n) {
    int ch, i = 0;
    while ((ch = getchar()) != '\n')
        if (i < n) str[i++] = ch;  // 超過 n 後不再寫入,但 ch 仍在讀取
    str[i] = '\0';                 // 危險:i 可能已等於 n,str[n] 越界
    return i;
}

正確方案:動態內存管理(C 風格)

char* read_line_dynamic() {
    size_t capacity = 128;
    size_t len = 0;
    char* buf = malloc(capacity);
    if (!buf) return NULL;
    
    int ch;
    while ((ch = getchar()) != '\n' && ch != EOF) {
        if (len + 1 >= capacity) { // 預留 \0 位置
            capacity *= 2;
            char* new_buf = realloc(buf, capacity);
            if (!new_buf) { free(buf); return NULL; }
            buf = new_buf;
        }
        buf[len++] = (char)ch;
    }
    buf[len] = '\0';
    return buf; // 調用者負責 free
}

關鍵改進點

  • 雙倍擴容策略:均攤 O(1) 時間複雜度,避免頻繁 realloc。
  • 返回堆內存指針:打破固定緩衝區限制,調用者 free() 釋放。
  • 處理 EOF:文件重定向輸入時無換行符,需判斷 EOF。
  • 錯誤碼返回:分配失敗返回 NULL,調用者必須檢查。

C++ 現代寫法(推薦)

#include <string>
std::string read_line_cpp() {
    std::string line;
    std::getline(std::cin, line); // 自動處理內存、換行、EOF
    return line;
}

結論:C 語言手寫動態行讀取極易出錯,工程上能用 C++ string 絕不手寫 char*,必須用 C 時嚴格遵循「誰分配誰釋放、檢查返回值、邊界檢查」三原則。

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