简体   繁体   中英

How to fix linked-list Segmentation fault C

I'm trying to fix this problem of 'segmentation-fault' in the following codes, I maybe think i didn't get the whole picture that's why i keep obtaining segmentation-fault over segmentation-fault, Any help on deeply understanding this, will encourage me developing self analysis.

The code should be straightforward : given two lists,i want to erase from the first one all the elements that appears in the second too, And my effort was :

typedef struct EL {
    int info;
    struct EL *next;
} ElementoLista;

typedef ElementoLista *ListaDiElementi;

void filterLists(ListaDiElementi *lista1,ListaDiElementi *lista2) {

  ListaDiElementi aux = *lista1,aus = *lista2,corr;

  while(aux != NULL) {
    if(aux->info == aus->info) {    // Erase from the first
      corr = aux;
      aux = aux->next;
      free(corr);
    }           
    else {              
      if(aus != NULL)       //Increase the second
        aus = aus->next;
      else {
        aus = *lista2;          //Restart
        aux = aux->next;
      }
    }       
  }
}

There are a couple of issues with your code:

  • You'll get a segfault, when the second list is shorter than the other, because you do not check if aus is NULL in the first if-statement.

  • You'll get another segfault later, if an element in the middle of the first list is removed, because the predecessor of the deleted element still points to the original, but freed memory.

  • I don't know if this is an issue, but your algorithm only seems to work for sorted lists, have a look at those two lists for example [1,2] and [2,1].

To help you with your algorithm, we'd need to know how you like to handle duplicate elements and if lists are sorted or not.

I suppose nothing about the order of the element in the two lists, a solution can be :

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

typedef struct EL {
    int info;
    struct EL *next;
} ElementoLista;

ElementoLista * make(int i, ElementoLista * n)
{
  ElementoLista * r = malloc(sizeof(ElementoLista));

  if (r == NULL) {
    /* change that code with what you want */
    puts("out of memory");
    exit(-1);
  }

  r->info = i;
  r->next = n;
  return r;
}

/* I suppose nothing about the order of the element in the two lists */
void filterLists(ElementoLista ** plista1, ElementoLista * lista2) {
  /* have to work on plista1, not on a var valuing *plista1,
     to be able to update it when a cell is removed */
  while (*plista1 != NULL) {
    ElementoLista * p;

    /* is the info present in the second list ? */
    for (p = lista2; p != NULL; p = p->next) {
      if ((*plista1)->info == p->info) {
        /* remove the cell */
        ElementoLista * rmv = *plista1;

        *plista1 = (*plista1)->next;
        free(rmv);
        break;
      }
    }

    if (p == NULL)
      /* the current cell was not removed, go to the next */
      plista1 = &(*plista1)->next;
  }
}

void pr(ElementoLista * l)
{
  putchar('{');
  while (l != NULL) {
    printf(" %d", l->info);
    l = l->next;
  }
  puts(" }");
}

int main()
{
  ElementoLista * l1 = make(1, make(2, make(3, make(4, 0))));
  ElementoLista * l2 = make(3, make(1, 0));

  pr(l1);
  filterLists(&l1, l2);
  pr(l1);

  return 0;
}

I removed your typedef hidden the pointer, it is a bad idea to do that because this disturb the reader

As you can see it is useless to give the address of the pointer for the second list because that one is not modified

Execution :

{ 1 2 3 4 }
{ 2 4 }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM