0

I'm facing the segmentation fault error in the following dynamic linked list implementation; GDB shows the issue is on the node = node->next line in the "l_print" function of the linked-list ("LIST_CL.H" file). Anyone can help? I even tried "drawing debug" on paper but still I'm not getting the issue here.

Note: I report the whole code for both the insert and the print, in case it's useful. Therefore LIST.C file include the "switch case 6" to insert the element ("l_add" function in "LIST_CL.H" file) and the "switch case 1" to print the list ("l_print" function in "LIST_CL.H" file)

Note: The issue only happen when the list has one or more items. There's no errors when the list is empty ("list_cl" struct has NULL for both head and tail nodes)

LIST.C:

#include <stdio.h>
#include <string.h> //for strcpy
#include "cl_list.h"
#include "list_cl.h"

#define STRING_SIZE 25

int main(){
   list_cl class = L_EMPTYLIST_CL;
   
   puts("Select command:");
   puts("0. Exit.");
   puts("1. Insert node.");
   puts("6. Print all nodes in the linked list.");
   
   int k = 0;
   scanf("%d", &k);
   while(k != 0){
      switch(k){
         case 1:
            char cf[17] = "";
            char first_name[STRING_SIZE] = "";
            char last_name[STRING_SIZE] = "";
            getchar();
            
            puts("Insert name:");
            fgets(first_name, sizeof(first_name), stdin);
            puts("Insert surname:");
            fgets(last_name, sizeof(last_name), stdin);
            puts("Insert fiscal code:");
            fgets(cf, sizeof(cf), stdin);
            
            client cliente;
            strcpy(cliente.cf, cf);
            cliente.first_name = first_name;
            cliente.last_name = last_name;
            
            class = l_add_cl(class, cliente);
            
            puts("Node inserted.");
            
            break;
         case 6:
            l_print(class);
            break;
         default:
            break;
      }
      scanf("%d", &k);
   }
   
}

LIST_CL.H:

list_cl l_add_cl(list_cl l, client p){

   l_node node;
   node.id = 1;
   node.person = p;
   node.next = NULL;

   if(l.head == NULL){
      //List is empty
      l.head = &node;
      l.tail = &node;
   } else {
      l.tail -> next = &node;
      l.tail = &node;
   }
   
   return l;
}

void l_print(list_cl l){
   l_node *node = NULL;
   node = l.head;
   while(node != NULL){
      //client *cliente = &node->person;
      //printf("ID Elemento: %d | Name: %s Surname: %s Fiscal Code: %s", node->id, cliente->first_name, cliente->last_name, cliente->cf);
      node = node->next; // SEGMENTATION FAULT ERROR HERE!
   }
}

CL_LIST.H:

#include "client.h"
typedef struct _node {
   unsigned int id;
   client person;
   struct _node *next;
} l_node;
typedef struct {
   l_node *head;
   l_node *tail;
} list_cl;
#define L_EMPTYLIST_CL {NULL,NULL}

CLIENT.H:

typedef struct {
   char cf[17];
   char *first_name;
   char *last_name;
} client;
4
  • 3
    l_add_cl is saving the address of a local variable. When that goes out of scope at the end of the function you have a dangling pointer. Commented Dec 15, 2022 at 0:22
  • you have to allocate your clietns, nodes etc on the heap using malloc Commented Dec 15, 2022 at 0:23
  • Thanks you, solved! You both were right, saving the "node" variable address was causing the segmentation fault error, and plus, not allocating with malloc was causing data inconsistency (for the first_name and last_name pointers ), I'm going to post the fixed code here Commented Dec 16, 2022 at 22:04
  • Does this answer your question? "Segmentation fault" error message for simple list in c Commented Dec 16, 2022 at 22:19

1 Answer 1

0

Fixed code:

LIST.C:

#include <stdio.h>
#include <string.h> //for strcpy
#include "cl_list.h"
#include "list_cl.h"

#define STRING_SIZE 25

int main(){
   list_cl class = L_EMPTYLIST_CL;
   
   puts("Seleziona un comando:");
   puts("0. Exit.");
   puts("1. Insert one node.");
   puts("6. Print all nodes.");
   
   int k = 0;
   scanf("%d", &k);
   while(k != 0){
      switch(k){
         case 1:
            char cf[17] = "";
            //char first_name[STRING_SIZE] = ""; THIS CAUSE DATA INCONSISTENCY
            //char last_name[STRING_SIZE] = ""; THIS CAUSE DATA INCONSISTENCY
            char *first_name = malloc(sizeof(char)*STRING_SIZE);
            char *last_name = malloc(sizeof(char)*STRING_SIZE);

            getchar();
            
            puts("Insert name:");
            //fgets(first_name, sizeof(first_name), stdin); ISSUE WITH SIZE OF FIRST_NAME
            fgets(first_name, sizeof(char)*STRING_SIZE, stdin);
            puts("Insert surname:");
            //fgets(last_name, sizeof(last_name), stdin); ISSUE WITH SIZE OF LAST_NAME
            fgets(last_name, sizeof(char)*STRING_SIZE, stdin);
            puts("IInsert fiscal code:");
            fgets(cf, sizeof(cf), stdin);
            
            client *cliente = malloc(sizeof(client));
            strcpy(cliente->cf, cf);
            cliente->first_name = first_name;
            cliente->last_name = last_name;
            
            class = l_add_cl(class, *cliente);
            
            puts("Element inserted.");
            
            break;
         case 6:
            l_print(class);
            break;
         default:     
            break;
      }
      puts("Select command:");
      scanf("%d", &k);
   }
   
}

LIST_CL.H

list_cl l_add_cl(list_cl l, client p){

   l_node *node = malloc(sizeof(struct _node));
   node->id = 1;
   node->person = p;
   node->next = NULL;

   if(l.head == NULL){
      //Empty list
      l.head = node;
      l.tail = node;
   } else {
      l.tail -> next = node;
      l.tail = node;
      l.tail -> next = NULL;
   }
   
   return l;
}

void l_print(list_cl l){
   l_node *node = NULL;
   node = l.head;
   while(node != NULL){
      client *cliente = &node->person;
      printf("ID Element: %d | Name: %s Surname: %s Fiscal code: %s", node->id, cliente->first_name, cliente->last_name, cliente->cf);
      node = node->next;
   }
}

CL_LIST.H

#include "client.h"
typedef struct _node {
   unsigned int id;
   client person;
   struct _node *next;
} l_node;
typedef struct {
   l_node *head;
   l_node *tail;
} list_cl;
#define L_EMPTYLIST_CL {NULL,NULL}

CLIENT.H

typedef struct {
   char cf[17];
   char *first_name;
   char *last_name;
} client;
Sign up to request clarification or add additional context in comments.

4 Comments

You fixed the code by allocating first_name and last_name with malloc, but cf just works as is. cf is a character array whereas first_name and last_name are pointers. Perhaps it would have been easier to just have first_name and last_name as character arrays too. Simple, consistent, less room for error.
@n.m. Thanks you I noticec that but the file CLIENT.H was as given by the teacher, I guess for pointing this difference and because while fiscal code has a fixed length, name and surname has not.
By the way I later noticed an issue with the size of the string saved by the fgets, it looks that the instruction fgets(first_name, sizeof(first_name), stdin) was not saving all the characters in the string, and kept something out on the stdin (the next fgets was simply skipped). I solved with fgets(first_name, sizeof(char)*STRING_SIZE, stdin);. The error didn't happen when the input string length was less than 5 or 6 characters, I guess sizeof(some_ptr_variable) just take the length of the address (eg. 0x-----)
Right, sizeof first_name is the size of the pointer, not the thing pointed to.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.