связанный список ошибок сегментации

Я вижу похожую тему, но они мне не помогли. У меня есть связанный список и функция для вставки элементов.

struct node{
    int data;
    struct node* next;
} node;

struct node* head;

void insert(struct node* head,int x);
int main(){
    struct node* head = (struct node*) malloc(sizeof(struct node));
    int x;
    while(1){
        printf("Please enter number\n");
        scanf("%i", &x);
        insert(head,x);
        print(head); // function that works
    }
    return 0;
}
void insert(struct node* head,int x){
    struct node* temp = malloc(sizeof(struct node));
    temp->data = x;
    temp->next = NULL;
    if(head->next != NULL) temp->next = head;
    head = temp;
    free(temp);
}

GDB сообщает, что я получаю ошибку сегментации в строке с конструкцией if:

if(head->next != NULL) temp->next = head;

В чем моя ошибка?


person user3181029    schedule 10.01.2014    source источник
comment
Убедитесь, что сама голова равна нулю   -  person James Reed    schedule 10.01.2014


Ответы (3)


Да, конечно, это приведет к ошибке сегментации. В состоянии if вы получаете доступ к head->next. head - это просто указатель типа struct node. Сначала выделите место в памяти, а затем получите доступ к полю. Прямо сейчас вы обращаетесь к (head->next), который является несоответствующим адресом в памяти, и ядро ​​выдает "ошибку сегментации" процессу. Например, сделайте struct node* head = malloc(sizeof(struct node));, и тогда можно будет получить доступ к head->next.

person Sumeet_Jain    schedule 10.01.2014
comment
Я привожу в качестве аргумента голову, я не понимаю, как это поможет. В любом случае я сделал новый динамически выделяемый var и установил его = head. Я все еще получаю сег. вина. - person user3181029; 10.01.2014
comment
Что ж, в функции печати вы можете получить доступ к освобожденной памяти. Вы можете освободить память в функции печати после ее доступа. - person Sumeet_Jain; 10.01.2014
comment
Я проголосовал против :( только потому, что никто не указал точно свою проблему. - person Sumeet_Jain; 10.01.2014
comment
user3181029 - Программа работала правильно? Я имею в виду, когда вы вводите число, оно должно добавляться в начало связанного списка? - person user3181029; 10.01.2014
comment
Да, это так. Никто не знает, что вы делаете в функции печати. Я закомментировал функцию печати. - person Sumeet_Jain; 10.01.2014

Вам необходимо проверить head перед звонком if(head->next != NULL) temp->next = head;. head может содержать NULL. Так что добавьте if(head != NULL) перед if(head->next != NULL) temp->next = head;

РЕДАКТИРОВАТЬ: Если вы разместили полный код, задавая вопрос, вам легко будет помочь вам должным образом. Теперь люди думают, что мы ответили неправильно, и голосуют против. хорошо, в любом случае вот мой ответ. Вы не должны вызывать free(temp); в самой функции вставки. Потому что вы собираетесь получить доступ к этой памяти в print функции. Вы освобождаете выделенную память в insert() себе и пытаетесь получить доступ в функции печати. Это вызывает ошибку сегментации. Удалите free(temp); из функции вставки.

person Chinna    schedule 10.01.2014
comment
Я получаю сег. опять ошибка, вот что я сделал: if (head! = NULL) {if (head- ›next! = NULL) temp-› next = head; } - person user3181029; 10.01.2014
comment
@ user3181029 вы выделили память для головы перед тем, как передать ее в insert ()? - person Chinna; 10.01.2014
comment
Да, но я не опубликовал основную функцию, извините, я опубликовал ее сейчас. Это моя основная функция после добавления туда головы и удаления ее из глобалов. - person user3181029; 10.01.2014

Обратите внимание, что вы объявляете две переменные с одинаковым именем (head), но в разных областях:

struct node* head;

void insert(struct node* head,int x);
int main()
{
  struct node* head = (struct node*) malloc(sizeof(struct node));

В функции вставки вы разыменовываете 'head' перед проверкой, является ли 'head' NULL или нет. Всегда проверяйте наличие null и никогда ничего не предполагайте. В конце функции вы освобождаете вновь созданный узел, это тоже неверно. Наконец, аргумент функции вставки неверен, вам нужно передать адрес указателя, чтобы иметь возможность изменить то, на что указывает заголовок.

Вместо этого функция должна выглядеть примерно так

void insert(struct node** head,int x)
{
  struct node* temp = malloc(sizeof(struct node));
  temp->data = x;
  temp->next = NULL;

  assert( head != NULL ); // should always be an address

  if ( *head == NULL ) 
  {
    *head = temp; // done, first in list
  }
  else // insert as first in list
  {
    tmp->next = *head; 
    *head = tmp;       
  }
}

затем вы должны назвать это так:

insert(&head,x);
person AndersK    schedule 10.01.2014