我正在使用WSL Ubuntu-20.04 LTS和編譯gcc.
我正在準備一些示例來向 CS 學生教授 C 的基礎知識,當我閱讀指定的初始化程式時,以下代碼導致錯誤,
typedef enum {male, female} sexe;
struct human_t {
char * name;
char * title;
sexe gender;
};
struct human_t steve = {.name = "Steve",
.title = "Mr.",
.gender = male
};
strcpy(steve.name, "AA");
并且閱讀關于strcpy目標緩沖區的手冊比"AA"我完全不知道為什么這不起作用。
我還觀察到以下內容:
struct human_t steve = {.name = "Steve",
.title = "Mr.",
.gender = male
};
char * new_name = "Gobeldydukeryboo";
realloc(steve.name, strlen(new_name));
strcpy(steve.name, new_name);
這將回傳錯誤realloc(): invalid pointer。
閱讀有關realloc指標的手冊必須是通過malloc呼叫回傳的,它才能作業。我有一種感覺,指定的初始化不呼叫malloc,這可以解釋為什么realloc失敗,但是它不能解釋為什么strcpy失敗。
這里發生了什么 ?
uj5u.com熱心網友回復:
struct human_t steve = {.name = "Steve",
.title = "Mr.",
.gender = male
};
這里name(and ) 使用字串字面title量的地址進行初始化。字串文字不是從堆中分配的,實際上它們(通常)是只讀的。因此,如果您想撰寫更健壯的代碼,則應始終分配字串文字。const char*
所以在第一個片段中,strcpy(steve.name, "AA");會嘗試寫入只讀記憶體并崩潰。如果你做了steve.name一個 const char,它會產生一個編譯器錯誤,你會很安全。
然后第二個片段,realloc(steve.name, strlen(new_name));將嘗試調整未分配的記憶體塊的大小malloc。所以你會崩潰。
此外,這根本不是您使用realloc的方式。你需要這樣做:
char *tmp = realloc(steve.name, strlen(new_name) 1);
if (!tmp) { perror("realloc error"); exit(1); }
strcpy(tmp, new_name);
steve.name = tmp;
要修復,請存盤字串的副本:
struct human_t steve = {.name = strdup("Steve"),
.title = strdup("Mr."),
.gender = male
};
這strdup是一個 POSIX 函式,但不是標準 C 函式,因此您可能需要自己定義它:
char *strdup(const char *src)
{
char *dst = src ? malloc(strlen(src) 1) : NULL;
if (dst) strcpy(dst, src);
return dst;
}
uj5u.com熱心網友回復:
在這份宣告中
struct human_t steve = {.name = "Steve",
.title = "Mr.",
.gender = male
};
name您使用字串文字的第一個字符的地址初始化了指標"Steve"。
然后在這個宣告中
strcpy(steve.name, "AA");
您試圖更改字串文字。
任何更改字串文字的嘗試都會導致未定義的行為。
相反,你可以寫
steve.name = "AA";
之后,指標name將指向字串字面量"AA"。
在這份宣告中
realloc(steve.name, strlen(new_name));
您正在嘗試重新分配由具有靜態存盤持續時間的字串文字占用的記憶體。但是您只能重新分配以前動態分配的記憶體。此外,通常您需要將呼叫的回傳地址分配給指標realloc。否則重新分配的記憶體地址會丟失,你就會有記憶體泄漏。
將資料成員名稱宣告為字符陣列,例如
struct human_t {
char name[10[;
char * title;
sexe gender;
};
或者總是動態分配一個記憶體來存盤一個字串,例如
struct human_t steve = {.name = malloc( 10 ),
.title = "Mr.",
.gender = male
};
strcpy( steve.name, "Steve" );
另一個資料成員也存在同樣的問題title。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/431178.html
