您忘記了在包含realloc()
的函數中將新值分配給*s
。
void test(void) // Unaltered; still broken!
{
char *c = malloc(strlen("I like coffe") + 1);
strcpy(c, "I like coffe");
char **s = &c;
while (strlen(*s) < 25)
my_function(s);
}
void my_function(char **s) // Fixed one way
{
char *w = *s;
size_t len = strlen(w) + 1; // Define and initialize len
char *tmp = realloc(w, len + 2);
if (tmp != NULL)
w = tmp;
*s = w; // Reassign to `*s`
}
或者更簡單地說:
void my_function(char **s) // Fixed another way
{
char *w = *s;
size_t len = strlen(w); // Define and initialize len
char *tmp = realloc(w, len + 2);
if (tmp != NULL)
*s = tmp; // Reassign to `*s`
}
分配到w
只設置局部變量這是*s
複印件;它不會重置調用代碼中的指針。
請注意,即使使用此修復,test()
中的循環將運行很長時間,因爲沒有任何更改c
中字符串的長度。還有另一個問題:您沒有將s
的地址傳遞給my_function()
,因此my_function()
無法修改s
。
void test(void)
{
char *c = malloc(strlen("I like coffe") + 1);
strcpy(c, "I like coffe");
while (strlen(c) < 25)
{
my_function(&c);
strcat(c, "AZ"); // Grow string — not good in real code
printf("%2zu: <<%s>>\n", strlen(c), c);
}
}
void my_function(char **s)
{
char *w = *s;
size_t len = strlen(w) + 1; // Define and initialize len
char *tmp = realloc(w, len + 2);
if (tmp != NULL)
*s = tmp; // Reassign to `*s`
}
這會取消指向指向char的指針的指針test()
。如果這是至關重要的,那麼還有更多想法要做。
代碼尚未正式測試過!
現在測試的代碼 - 你能說「豬耳朵」嗎?複製錯誤材料的錯誤使我的測試代碼失敗。這是儀器化的工作版本 - valgrind
爲它提供了一個乾淨的健康法案。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void my_function(char **s)
{
char *w = *s;
size_t len = strlen(w) + 1; // Define and initialize len
printf("M1: %p: %2zu: <<%s>>\n", (void *)w, len, w);
char *tmp = realloc(w, len + 2);
if (tmp != NULL)
*s = tmp; // Reassign to `*s`
printf("M2: %p: %2zu: <<%s>>\n", (void *)*s, strlen(*s), *s);
}
static void test(void)
{
char *c = malloc(strlen("I like coffe") + 1);
if (c == 0)
{
fprintf(stderr, "Out of memory\n");
exit(EXIT_FAILURE);
}
strcpy(c, "I like coffe");
printf("T1: %p: %2zu: <<%s>>\n", (void *)c, strlen(c), c);
while (strlen(c) < 25)
{
my_function(&c);
printf("T2: %p: %2zu: <<%s>>\n", (void *)c, strlen(c), c);
if (c == NULL)
{
fprintf(stderr, "Out of memory\n");
exit(EXIT_FAILURE);
}
strcat(c, "AZ"); // Grow string — not good in real code
printf("T3: %p: %2zu: <<%s>>\n", (void *)c, strlen(c), c);
}
free(c);
}
int main(void)
{
test();
return 0;
}
Betcha你在擺弄「指針指針」時遇到了麻煩。拿起一張紙和一支二號鉛筆,離線(!)......「我說,'一張紙和一個二號鉛筆!'」......這段代碼是什麼實際上是在告訴計算機去做。 「你的方式的錯誤」應該變得明顯。 (並且,不,我*不*在這裏試圖暴露。) –
你永遠不會用新地址重新分配父母的背影。不保證realloc(addr)返回地址。實際上,對於大多數自定義分配器,它通常不會。嘗試在代碼中執行'* s = tmp'而不是'w = tmp'。另外,如果realloc失敗(返回NULL),則需要將* s設置爲NULL。 – digger
@digger:No;如果realloc()返回NULL,則原始分配不變。 –