錯誤程式碼
char *strcopy(char *dest, char *source) {
if (source == NULL) return NULL;
dest = (char *)malloc(strlen(source) + 1); // 錯誤:修改區域指標副本
char *p = dest;
while (*source) *p++ = *source++;
*p = '\0';
return dest;
}
int main() {
char *src = "hello";
char *des = NULL; // 未配置記憶體
des = strcopy(des, src); // 依賴回傳值接收新位址
printf("%s\n", des);
free(des);
return 0;
}
問題分析
main 中 des 未初始化,若 strcopy 內部 malloc 失敗回傳 NULL,後續 printf 導致段錯誤。
- 函數參數
dest 是指標副本,內部 malloc 重新指向新記憶體,**不影響呼叫端原指標**;必須透過回傳值或雙重指標傳回新位址。
- 呼叫端需檢查回傳值是否為 NULL。
正確實作
// 方式一:回傳新配置指標(呼叫端須 free)
char *my_strdup(const char *src) {
if (!src) return NULL;
char *dst = malloc(strlen(src) + 1);
if (dst) strcpy(dst, src);
return dst;
}
// 方式二:呼叫端提供緩衝區(傳統 strcpy 風格)
char *my_strcpy(char *dst, const char *src) {
char *ret = dst;
while ((*dst++ = *src++));
return ret;
}
int main() {
const char *src = "hello";
// 方式一
char *p1 = my_strdup(src);
if (p1) { puts(p1); free(p1); }
// 方式二
char buf[100];
my_strcpy(buf, src);
puts(buf);
return 0;
}
關鍵點總結
- 指標傳遞為值傳遞,函數內修改指標指向不影響外部。
- 動態配置記憶體必須檢查回傳值。
- 慣用
strcpy(dst, src) 由呼叫端負責緩衝區配置,避免所有權混淆。