首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言字串拼接:strcat 模擬實現與緩衝區溢出風險分析

     編輯:關於C語言

C語言字串拼接:strcat 模擬實現與緩衝區溢出風險分析

原始碼存在**參數順序顛倒**、**返回值錯誤**、**無緩衝區檢查**三大缺陷。本文提供標準 `strcat` 實現、安全版 `strncat`、`strlcat` 最佳實踐。

strcat 標準語義

  • `char *strcat(char *dest, const char *src)`
  • 將 `src` 拼接到 `dest` 末尾 (覆蓋 `dest` 的 `\0`)
  • 返回 `dest` 起始位址
  • **呼叫者責任**:`dest` 必須有足夠空間容納結果 + `\0`

原始碼缺陷分析

// 原始碼:
char *my_strcat(char *dest, char *src) {  // src 應為 const
    char *ret = src;  // 錯誤:應返回 dest
    while (*src) src++;  // 找 src 末尾?應找 dest 末尾
    while (*src++ = *dest++) ;  // 參數順序反了!應 dest 接收 src
    return ret;  // 返回錯誤
}

正確標準實現

#include 

char *my_strcat(char *dest, const char *src) {
    assert(dest && src);
    
    char *ret = dest;
    
    // 1. 找到 dest 結束符
    while (*dest) dest++;
    
    // 2. 拼接 src (含 \0)
    while ((*dest++ = *src++) != '\0')
        ;
    
    return ret;
}

安全增強版:strncat (限制拼接長度)

char *my_strncat(char *dest, const char *src, size_t n) {
    assert(dest && src);
    
    char *ret = dest;
    while (*dest) dest++;
    
    while (n-- && *src) {
        *dest++ = *src++;
    }
    *dest = '\0';  // 確保結束符
    
    return ret;
}

最佳實踐:strlcat (BSD 風格,保證結束符、返回總長度)

// 非標準但廣泛可用 (BSD, Linux, macOS)
size_t strlcat(char *dest, const char *src, size_t dest_size) {
    size_t dlen = strlen(dest);
    if (dlen >= dest_size) return dlen + strlen(src);  // dest 已滿
    
    size_t n = dest_size - dlen - 1;  // 留 1 位給 \0
    char *d = dest + dlen;
    const char *s = src;
    
    while (n-- && *s) *d++ = *s++;
    *d = '\0';
    
    return dlen + (s - src);  // 返回嘗試建立的總長度
}

緩衝區溢出風險演示

int main() {
    char buf[10] = "hello";  // 容量 10,已用 6 (含\0),剩 4
    char *src = "world!";    // 長度 6
    
    // 危險:strcat 無長度檢查
    strcat(buf, src);  // 寫入 6 字元 + \0 = 7 字元,溢出 3 字元!
    // 結果:緩衝區溢出,未定義行為 (可能崩潰、靜默損壞、安全漏洞)
    
    // 安全:strncat
    char buf2[10] = "hello";
    strncat(buf2, src, sizeof(buf2) - strlen(buf2) - 1);  // 最多複製 3 字元
    // 結果:"hello wor"
    
    // 最佳:strlcat
    char buf3[10] = "hello";
    strlcat(buf3, src, sizeof(buf3));  // 自動處理邊界
    // 結果:"hello wor"
    
    return 0;
}

常見錯誤總結表

錯誤後果修正
參數順序反 (src, dest)邏輯完全錯誤標準為 (dest, src)
返回 src 而非 dest鏈式調用失效保存並返回 dest
src 非 const語義錯誤,阻礙優化const char *src
無緩衝區檢查溢出漏洞用 strncat/strlcat 或預先檢查
忘記確保 \0字串未正確終止strncat 手動補 \0,strlcat 自動

總結

`strcat` = **危險、無長度檢查、棄用**。現代代碼**強制使用 `strlcat` 或 `strncat` + 精確長度計算**。原始碼參數順序反、返回值錯、無 `const`,屬於基礎語義錯誤。面試必會:`strcat`/`strncat`/`strlcat` 三者差異、緩衝區溢出風險與防範、返回值語義差異 (指標 vs 長度)。

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