Связанные списки Аномалия перехода указателя в c. Указатель получает адрес из несуществующего местоположения - PullRequest
0 голосов
/ 31 августа 2018

Я написал программу для связанного списка новичков и удалил любой указанный узел из списка. Но при этом я не могу понять, почему, хотя я удалил рассматриваемый узел с помощью free (), как я могу получить ссылку на узел после него? Потому что код работает нормально, но я не могу понять, почему? Я также добавил несколько заявлений для печати, чтобы посмотреть, что происходит. Вот код:

#include <stdio.h>
#include <stdlib.h>

struct node{
  int key;
  struct node *next;
};
struct node *head = NULL;

void insert_first_node(int val){
  struct node *temp;
  temp = (struct node *)malloc(sizeof(struct node));
  temp->key=val;
  head = temp;
}

void insert(int val){
  struct node *temp = (struct node *)malloc(sizeof(struct node));
  struct node *s=head;
  temp->key=val;
  temp->next=NULL;
  while(s->next!=NULL)
  s=s->next;
  s->next=temp;
}

void delete(){
    int d;int i;
    printf("Enter the position of the node you want to delete\n");
    scanf("%d",&d);
    struct node *s=head;

    for(i=1;i<d-1;i++)
        s=s->next;

    printf("%d\n",s->key);
    printf("%d\n",s->next->key);
    printf("%d\n",s->next->next->key);

        free(s->next);

    printf("%d\n",s->key);
    printf("%d\n",s->next->key);
    printf("%d\n",s->next->next->key);

        s->next=s->next->next;

    printf("%d\n",s->key);
    printf("%d\n",s->next->key);
    printf("%d\n",s->next->next->key);

}

void print(){
    struct node *temp =head;
    printf ("\n[head] => ");
    while(temp!=NULL){
        printf("%d => ",temp->key);
        temp=temp->next;
    }
    printf("[end]\n");
}
void main(){
    int v;int x;
    insert_first_node(10);
    for(x=2;x<=10;x++){
        insert(x*10);
    }
    print();
    delete();
    print();
}

А вот и вывод:

[head] => 10 => 20 => 30 => 40 => 50 => 60 => 70 => 80 => 90 => 100 => [end]
Enter the position of the node you want to delete
4
30
40
50
30
0
50
30
50
60

[head] => 10 => 20 => 30 => 50 => 60 => 70 => 80 => 90 => 100 => [end]

Узел удаляется из списка, как и предполагалось, но не должен, так как я удалил 4-й узел из памяти, программа не должна иметь указатель на 5-й узел, но она выполняется чисто. КАК ??

Ответы [ 2 ]

0 голосов
/ 31 августа 2018

Хорошей практикой считается установка указателя на блок динамической памяти NULL сразу после его free для предотвращения сценариев двойного освобождения (free(NULL) безобидно) и бесполезных попыток получить к нему доступ.

inline void my_free(void **p)
{
    free(*p);
    *p = NULL;
}

Использование:

void *p = malloc(...); 

...

my_free(&p);

Доступ к динамической памяти после вызова free для указателя на нее - неопределенное поведение. Тот факт, что во время тестирования вы работали в вашей системе несколько раз, не следует понимать, что ваша программа верна; тестирование может показать только наличие ошибок, но не их отсутствие.

0 голосов
/ 31 августа 2018

Если вы обращаетесь к ранее освобожденной памяти, вы вызываете неопределенное поведение.
Это не значит, что вы получите ошибку, все может случиться.

Как вы описали, может также случиться, что программа работает нормально, но вы не можете полагаться на это поведение. Возможно, теперь он работает на вашей машине, но может пойти не так в любое другое время.

...