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

C 語言指針拼接字符串陷阱:字符串常量不可修改、必須用字符數組作目標緩衝區

     編輯:C 語言問答

C 語言指針拼接字符串陷阱:字符串常量不可修改、必須用字符數組作目標緩衝區

經典錯誤:嘗試將字符串拼接到字符串常量指向的內存區,導致未定義行為 (段錯誤/運行時錯誤)。

錯誤代碼分析


char *a = "hello";   // a 指向只讀數據段中的 "hello\0"
char *b = "rabbit";  // b 指向只讀數據段中的 "rabbit\0"
strcat_(a, b);       // 嘗試寫入 a 指向的只讀內存 → 崩潰

記憶體佈局解析

正確實現:目標用字符數組


#include <stdio.h>
#include <string.h>

// 安全拼接:目標緩衝區需足夠大
void safe_strcat(char *dest, size_t dest_size, const char *src) {
    size_t dest_len = strlen(dest);
    if (dest_len + strlen(src) + 1 > dest_size) {
        fprintf(stderr, "緩衝區不足\n");
        return;
    }
    strcat(dest, src);  // 標準庫函數已處理 \0
}

int main() {
    char a[20] = "hello";   // ✅ 棧上字符數組,可寫,大小 20
    char *b = "rabbit";     // 源字符串常量無妨
    safe_strcat(a, sizeof(a), b);
    printf("拼接結果: %s\n", a);  // hello rabbit
    return 0;
}

手寫 strcat 實現 (教學用)


char* my_strcat(char *dest, const char *src) {
    char *d = dest;
    while (*d) d++;        // 移至 dest 末尾 \0
    while ((*d++ = *src++)); // 複製 src 含 \0
    return dest;
}

關鍵避坑清單

  1. 目標緩衝區必須可寫:字符數組 `char buf[N]` 或 `malloc` 分配
  2. 目標緩衝區必須足夠大:`strlen(dest) + strlen(src) + 1 ≤ size`
  3. 源字符串可以是常量:`const char *src` 只讀無妨
  4. 返回值習慣:返回 `dest` 便於鏈式調用
  5. 生產代碼用標準庫:`strcat`/`strncat`/`strlcat` (BSD) 經過優化測試

編譯器輔助檢測

  • GCC/Clang:`-Wwrite-strings` 將字符串常量類型視為 `const char*`,賦值給 `char*` 會警告
  • C++ 編譯器:直接報錯 `invalid conversion from 'const char*' to 'char*'`
  • 靜態分析工具:Cppcheck、Clang Static Analyzer 可檢測緩衝區溢出風險
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
聲明存儲區可寫性生命週期
`char *p = "lit";`只讀數據段 (`.rodata`)❌ 只讀程序全周期
`char arr[] = "lit";`棧 (局部) / 數據段 (全局)✅ 可寫作用域/程序全周期
`char *p = malloc(n);`堆✅ 可寫手動 free 釋放