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

C 語言 gets 與 for 循環死循環雙重缺陷分析與修正

     編輯:程式設計綜合問答

原代碼問題 (推測重構)

char str[100];
gets(str); // 缺陷 1: gets 不檢查邊界,極易緩衝區溢出,C11 已移除

for (int i = 0; str[i] != '\0'; ) { // 缺陷 2: 循環體內無 i++,死循環
    // 處理字符...
    // 缺少 i++ 導致 i 永遠為 0,條件 str[0] != '\0' 永真 (除非空串)
}

缺陷詳解

問題危害修正方案
使用 `gets()` 不限制輸入長度,超出數組邊界覆蓋棧內存 → 程序崩潰、任意代碼執行漏洞。C99 標記棄用,C11 正式移除。 用 `fgets(str, sizeof(str), stdin)`,自動讀取換行符,需手動去除尾部 `\n`。或 `scanf("%99s", str)` (不含空格)。
for 循環缺少增量 循環變量 `i` 不變,條件永真 → **死循環**,CPU 100%,程序無響應。 在循環體末尾或 `for` 第三部分添加 `i++`:
`for (int i = 0; str[i]; i++) { ... }`

安全讀取字符串最佳實踐

// 方案 1: fgets (推薦,保留空格、讀取整行)
char line[256];
if (fgets(line, sizeof(line), stdin)) {
    line[strcspn(line, "\n")] = '\0'; // 移除尾部換行符
    // 處理 line
}

// 方案 2: scanf 寬度限制 (不含空格)
char word[100];
if (scanf("%99s", word) == 1) { // %99s 限制最多讀 99 字符
    // 處理 word
}

// 方案 3: 動態行讀取 (POSIX getline / C11 可選)
char *line = NULL;
size_t len = 0;
ssize_t read = getline(&line, &len, stdin);
if (read != -1) {
    if (line[read-1] == '\n') line[read-1] = '\0';
    // 處理 line
    free(line);
}

循環遍歷字符串標準模式

// 模式 1: for 循環 (最常用)
for (int i = 0; str[i] != '\0'; i++) {
    process(str[i]);
}

// 模式 2: while 循環 (指針算術)
char *p = str;
while (*p) {
    process(*p++);
}

// 模式 3: 範圍 for (C++ 僅供參考)
for (char c : str) { // C++11
    process(c);
}

編譯器檢查建議

  • 編譯加 `-Wall -Wextra -Werror=implicit-function-declaration` (GCC/Clang) 會報警 `gets` 隱式聲明 (C11 移除)。
  • 靜態分析工具 (Cppcheck, Clang Static Analyzer, Coverity) 會標記 `gets` 為高危、循環變量未修改為邏輯錯誤。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved