2014-12-03 3 views
0
#include<stdio.h> 
#include<stdlib.h> 
void add(char **p); 
void print(char **p); 
int cnt=0; 
main() 
{ 
    int option; 
    char **p=NULL; 
while(1) 
{ 
    printf("------MENU-----\n"); 
    printf("1>input\n 2>print\n3>exit\n"); 
    printf("enter ur choice\n"); 
    scanf("%d",&option);getchar(); 
switch(option) 
{ 
    case 1: add(p); 
      break; 
    case 2: print(p); 
      break; 
    case 3: return; 
    default: printf("Invalid option\n"); 

} 
} 
} 
void add(char **p) 
{ 
    int i; 
    p=(char**)realloc(p,(cnt+1)*sizeof(char*)); 
    if(p==NULL) 
    { 
     printf("Error: memory not available\n"); 
     return; 

    } 
    p[cnt]=NULL; 
    p[cnt]=(char*)realloc(p[cnt],20*sizeof(char)); 

    puts("enter a name"); 
    gets(p[cnt]); 
    cnt++; 
    printf("cnt=%d\n",cnt); 
} 
void print(char **p) 
{ 
    int i; 
    for(i=0;i<cnt;i++) 
    printf("p[%d]=%s\n",i,p[i]); 
} 

В приведенном выше коде я создаю базу данных имен. Для этого я использую динамическое распределение памяти. Я выделяю память для 2D-массива, используя массив методов указателей. Когда я выполняю эту программу на gcc компилятор, я получаю ошибка сегментации. Я не понимаю, почему это происходит? Не могли бы вы рассказать мне, где ошибка?Значение двойного указателя и тройного указателя в этом фрагменте кода

+0

В дополнение к тому, что уже упоминалось в ответах ниже о том, что переменная 'p' является локальной в функции' add', я уверен, что вы должны инициализировать 'p = malloc (...)' для начала, поскольку функция 'realloc' ожидает (как входной аргумент) указателя на сегмент памяти, ранее выделенного либо' malloc', либо 'realloc'. –

+0

Некоторые подсказки: используйте отладчик, последовательно отступайте от своего кода, избегайте 'get', не бросайте возвращаемые значения' malloc'/'realloc',' sizeof (char) 'всегда 1. –

+0

@barakmanos: My C standard говорит: «Если' ptr' - нулевой указатель, функция 'realloc' ведет себя как функция' malloc'. Но все же, если 'print' вызывается без предшествующего' add', указатель равен 0. –

ответ

0

Прохождение по ссылке. Вам необходимо передать адрес вашего указателя, чтобы убедиться, что изменения в функции add() отражены в main(). Избегайте использования gets()

В этом случае

add(&p); 

Соответственно ваше add() определение функции следует изменить, чтобы справиться с этим. Или другой путь для функции добавить, чтобы сделать необходимые ассигнования и вернуть этот адрес указателя

char **add(); 

Проверьте код ниже:

char **add(char **p) 
{ 
    int i; 
    p=(char**)realloc(p,(cnt+1)*sizeof(char*)); 
    if(p==NULL) 
    { 
     printf("Error: memory not available\n"); 
     return; 

    } 
    p[cnt]=NULL; 
    p[cnt]=(char*)realloc(p[cnt],20*sizeof(char)); 

    scanf("%s",p[cnt]); 
    cnt++; 
    printf("cnt=%d\n",cnt); 
    return p; 
} 

Таким образом, ваш вызов должен быть:

p = add(p); 
1

p в main передается в размере add по стоимости. add изменяет местную копию, но не оригинал p.

Помимо ужасного форматирования и все, что нужно передать указатель на ваши main «ы p к add:

... 

    case 1: add(&p); 
... 

void add(char ***p) 
{ 
    int i; 
    *p = realloc(*p,(cnt+1)*sizeof(char*)); 
    if(*p==NULL) 
    { 
     printf("Error: memory not available\n"); 
     return; 

    } 
    (*p)[cnt]=NULL; 
    (*p)[cnt]=realloc((*p)[cnt],20*sizeof(char)); 

    puts("enter a name"); 
    gets((*p)[cnt]); 
    cnt++; 
    printf("cnt=%d\n",cnt); 
} 
1

В основном, все, что вам сделать, это назначить p = NULL, а затем использовать этот указатель NULL в print , что вызывает segfault. Обратите внимание, что add(p) эквивалентно add(NULL) и не изменяется p. Возможно, вы имели в виду передать адрес с add(&p)? Если это так, вам нужно немного поиграть с номером *.

0

В функции добавления создается копия 2D-указателя p, и обновление этой указатель не будет отражено в основной функции. Быстрое решение этой проблемы - вернуть 2D-указатель 'p' из функции добавления.

char** print(char **p) 
{ 
    .... 
    .... 
    return p; 
} 
0

Помимо всего прочего, я не думаю, что кто-то упоминается о realloc ловушку отказа перераспределения. Предположим, что этот звонок

p=(char**)realloc(p,(cnt+1)*sizeof(char*)); 

не может выделить новую память: что тогда происходит? Да, вы получите NULL: но память, которую была выделена, и который p указывает на, делает не получает free 'd. Мгновенная утечка памяти.

Вы сусло вызов realloc так:

char* pTemp = realloc(p, cnt + 1); 
if(pTemp != NULL) 
{ 
    p = pTemp;    // Now safe to update p 
} 
else 
{ 
    // Error handling as required, possibly including freeing p 
} 

Еще одна причина не использовать realloc. Это не значит, что вы очень сильно делаете буфер, копируя себя ИМХО.

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