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

C 語言字串複製深度解析:strdup 避免常數區修改陷阱

     編輯:關於C語言

C 語言字串複製:strdup 實戰指南

C 語言字串字面常數儲存在唯讀常數區,嘗試修改導致未定義行為(通常崩潰)。strdup 在堆上分配記憶體並複製字串,提供可修改的副本,是字串處理的安全基石。

問題場景

char *s = "hello c";   // s 指向唯讀常數區
s[0] = 'a';            // 崩潰!Segmentation fault

char arr[] = "hello c"; // arr 在堆疊,內容為副本,可修改
arr[0] = 'a';           // OK

char *p = arr;          // p 指向堆疊陣列
p[0] = 'b';             // OK,但修改的是 arr

strdup 解決方案

#include <string.h>  // POSIX 標準,非 C 標準庫
#include <stdlib.h>  // free 需要

char *s = "hello c";
char *copy = strdup(s);  // malloc + strcpy,返回堆上副本

copy[0] = 'a';           // 安全修改
copy[1] = 'b';
printf("原字串: %s\n", s);      // hello c
printf("副本: %s\n", copy);     // abllo c

free(copy);  // 必須釋放!

strdup 內部實現原理

char *strdup(const char *s) {
    size_t len = strlen(s) + 1;  // 含結束符
    char *p = malloc(len);
    if (p) memcpy(p, s, len);
    return p;  // 失敗返回 NULL
}

跨平台注意事項

  • POSIX 標準:Linux/macOS 內建,<string.h>
  • Windows (MSVC):_strdup,需 <string.h> 或 <stdlib.h>
  • 可攜性寫法:
    #ifdef _WIN32
    #define strdup _strdup
    #endif
  • C23 標準化:strdup 正式納入 C23,未來可直接使用

手動實現替代方案

char *my_strdup(const char *s) {
    if (!s) return NULL;
    size_t len = strlen(s) + 1;
    char *p = malloc(len);
    if (p) strcpy(p, s);
    return p;
}

相關函數對比

函數分配記憶體複製長度用途
strdup是 (malloc)整串含 \0完整複製
strndup是指定 n 字元部分複製 (POSIX.1-2008)
strcpy否 (需預先分配)整串緩衝區複製
strncpy否指定 n固定長度,不保證 \0 結尾
memcpy否指定位元組二進制複製,不看 \0

最佳實踐

  1. 字面常數需修改時,必須 先 strdup 到堆
  2. 複製後記得 free,避免洩漏
  3. 檢查返回值 NULL(OOM 情況)
  4. 偏好 strndup 限制長度,防止惡意長字串耗盡記憶體
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved