Вы забыли присвоить новое значение *s
в функции, которая содержит realloc()
.
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`
}
Это устраняет указатель на указатель на символ в 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 у вас возникают проблемы с помощью «указателей на указатели». Возьмите листок бумаги и карандаш номер два и отработайте ... в автономном режиме (!) ... «Я сказал:« Листок бумаги и карандаш номер два! »... ... что этот фрагмент кода на самом деле говорит компьютеру. «Ошибка ваших путей» должна стать очевидной. (И, нет, я * не * стараюсь быть snarky здесь.) –
Вы никогда не переназначаете родителя с новым адресом. Нет никакой гарантии, что realloc (addr) возвращает addr. На самом деле, с большинством пользовательских распределителей, обычно этого не будет. Попробуйте сделать '* s = tmp', а не' w = tmp' в вашем коде. Кроме того, если realloc выходит из строя (возвращает NULL), вам нужно установить * s в NULL. – digger
@ digger: Нет; если 'realloc()' возвращает NULL, исходное распределение не изменяется. –