2015-05-14 3 views
0
void test(){ 
    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){ 
    char *w = *s; 

    char *tmp = realloc(w, len + 2);//Error HERE. *s gets = "" 
    if(tmp != NULL) 
    w = tmp; 
    for(i= len; i>=p; i--){ 
     w[i+1] = w[i]; 
    } 
    w[p] = c;  
} 

Эта функция используется, чтобы вставить новый символ в поле char *.
Кроме того, эта функция находится внутри цикла while. Он работает нормально, но в 3-й раз цикл работает, он просто устанавливает *s = "".
Я думал, что с помощью char *tmp я мог бы хранить данные, если произойдет что-то неправильное. Я не могу понять, почему P *s настроен на пустую строку.Указатель установки Realloc на пустой

+1

У Betcha у вас возникают проблемы с помощью «указателей на указатели». Возьмите листок бумаги и карандаш номер два и отработайте ... в автономном режиме (!) ... «Я сказал:« Листок бумаги и карандаш номер два! »... ... что этот фрагмент кода на самом деле говорит компьютеру. «Ошибка ваших путей» должна стать очевидной. (И, нет, я * не * стараюсь быть snarky здесь.) –

+0

Вы никогда не переназначаете родителя с новым адресом. Нет никакой гарантии, что realloc (addr) возвращает addr. На самом деле, с большинством пользовательских распределителей, обычно этого не будет. Попробуйте сделать '* s = tmp', а не' w = tmp' в вашем коде. Кроме того, если realloc выходит из строя (возвращает NULL), вам нужно установить * s в NULL. – digger

+1

@ digger: Нет; если 'realloc()' возвращает NULL, исходное распределение не изменяется. –

ответ

3

Вы забыли присвоить новое значение *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; 
} 
+0

Я думал, что, поскольку я не выделял память для 'w', только что сделал' w' указывает на то же локальное, что и '* s', это изменило бы оба. Я не думал, что это всего лишь копия. И почему это происходит только в третий раз, а не с первого запуска. – PlayHardGoPro

+0

Легко путать, но 'w' содержит копию' * s'. Изменение «w» изменяет локальную копию, а не оригинал. –

+0

Я только что сделал еще одно испытание. Эти функции находятся в файле separeted.c. Когда 'my_function()' закончен и возвращается для функции вызывающего абонента. Я вижу измененное значение '* s'. Как, если это просто копия? Так запутанный ха-ха – PlayHardGoPro

Смежные вопросы