Segmentation fault in linked list . Need Help to understand - c

I`m trying to do a linked list, but it's giving me segmentation fault error.
Here`s code:
typedef struct{
char diretor[50];
char nome[50];
}Filme;
typedef struct{
Filme filme;
struct Nodo *proximoNodo;
}Nodo;
void inserirFinal(Nodo **nodo_inicial)
{
Nodo *novo_nodo, *iterador;
iterador = *nodo_inicial;
novo_nodo = malloc(sizeof(Nodo));
adicionarNovoFilme(novo_nodo);
novo_nodo->proximoNodo = NULL;
if(iterador == NULL)
*nodo_inicial = novo_nodo;
else
{
while(iterador != NULL)
iterador = iterador->proximoNodo;
iterador->proximoNodo = novo_nodo;
}
}
void adicionarNovoFilme(Nodo *nodo)
{
Filme filme;
printf("Diretor:");
gets(filme.diretor);
printf("Nome:");
gets(filme.nome);
nodo->filme = filme;
}
The code should insert a new node at the end of a linked list (if it was empty, it started one)
The method would receive a pointer to a pointer that would be the iterator of the list in the main.
I'm don't know why it's giving segmentation error.

while(iterador != NULL)
iterador = iterador->proximoNodo;
stops when iterador == NULL. So when you then do
iterador->proximoNodo = novo_nodo;
you're dereferencing a null pointer.
You need to change the condition to:
while (iterador->proximoNodo != NULL)
This will stop when iterador points to the last node, it won't go past it.

Related

Function returns the oldest value in linked list

This is a function (last) that returns the oldest value in linked list (the last node):
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int val;
struct node *next;
}Elem, *Pointer;
Pointer init() { return NULL; }
void last(Pointer l)
{
while (l != NULL)
{
l = l->next;
}
printf("%d",l->val);
}
int main(void) {
Pointer myl =
insert(3, insert(7, insert(5,
insert(11, insert(1, init ())))));
last(myl);
}
so the function (last) takes a pointer that points to a linked list, and in a while loop it moves the pointer to the last node and then prints its value.
Error is: exited, segmentation fault.
Since checking for NULL l is your exit condition from the loop, when you reach the end of the loop
while (l != NULL)
{
l = l->next;
}
printf("%d",l->val);
l is NULL (otherwise you would still be looping!). So in the following printf you are dereferencing a NULL pointer and this results in a segmentation fault.
You can modify your function in the following way:
void last(Pointer l)
{
if ( l != NULL )
{
while (l->next != NULL)
{
l = l->next;
}
printf("%d",l->val);
}
}
Just peek in the next field of the element, after making sure that the list is not empty (NULL list pointer).
Never hide pointers behind the typedefs. It makes programs hard to read and error prone.
typedef struct node {
int val;
struct node *next;
}Elem;
This is something absilutelly horrible - avoid
insert(3, insert(7, insert(5,
insert(11, insert(1, init ())))));
The function. Check if the next value is NULL. IMO better return pointer and then do something with it. Also Always check if parameter is valid.
Elem *last(Elem *first)
{
if(first)
{
while(first -> next != NULL)
{
first = -first -> next;
}
}
return first;
}
Print it
printf("%d\n", last(myl) -> val);

Segmentation fault while creating a linked list

I am writing a small program which stores data and key inside a linked list structure, and retrieves data based on a key from the user. The program also checks whether it is a unique key and if it so it stores the data by creating a node at the front of the list. But the below code throws segmentation fault all the time.
#include<stdlib.h>
/* Node having data, unique key, and next */.
struct node
{
int data;
int key;
struct node *next;
}*list='\0',*p;
/* Create a node at the front */
void storeData(int data_x,int key_x)
{
int check_key;
position *nn; //nn specifies newnode
nn=(position)malloc(sizeof(struct node));
/* Segmentation Fault occurs here */
if(list->next==NULL)
{
nn->next=list->next;
nn->data = data_x;
nn->key = key_x;
list->next = nn;
}
else
{
check_key=checkUniqueKey(key_x);
if(check_key != FALSE)
{
printf("The entered key is not unique");
}
else
{
nn->data = data_x;
nn->key = key_x;
nn->next=list->next;
list->next=nn;
}
}
}
/* Retreive data based on a key */
int retreiveData(int key_find)
{
int ret_data = NULL;
p=list->next;
while(p->next != NULL)
{
if(p->key == key_find)
{
ret_data = p->data;
break;
}
p=p->next;
}
return(ret_data);
}
/* Checks whether user key is unique */
int checkUniqueKey(int key_x)
{
int key_check = FALSE;
p=list->next;
while(p->next != NULL)
{
if(p->key == key_x)
{
key_check = TRUE;
break;
}
p=p->next;
}
return(key_check);
}
The segmentation fault occurs in the storeData function after the dynamic allocation.
There are some problems in your code:
your list handling is flawed: you always dereference the global pointer list, even before any list items are created. You should instead test if the list is empty by comparing list to NULL.
type position is not defined. Avoid hiding pointers behind typedefs, this is a great cause of confusion, which explains your mishandling of list pointers.
avoid defining a global variable with the name p, which is unneeded anyway. Define p as a local variable in the functions that use it.
NULL is the null pointer, 0 a zero integer value and \0 the null byte at the end of a C string. All 3 evaluate to 0 but are not always interchangeable.
For better portability and readability, use the appropriate one for each case.
Here is an improved version:
#include <stdio.h>
#include <stdlib.h>
/* Node having data, unique key, and next */.
struct node {
int data;
int key;
struct node *next;
} *list;
/* Create a node at the front */
void storeData(int data_x, int key_x) {
if (checkUniqueKey(key_x)) {
printf("The entered key is not unique\n");
} else {
/* add a new node to the list */
struct node *nn = malloc(sizeof(struct node));
if (nn == NULL) {
printf("Cannot allocate memory for node\n");
return;
}
nn->data = data_x;
nn->key = key_x;
nn->next = list;
list = nn;
}
}
/* Retrieve data based on a key */
int retrieveData(int key_find) {
struct node *p;
int ret_data = 0;
for (p = list; p != NULL; p = p->next) {
if (p->key == key_find) {
ret_data = p->data;
break;
}
}
return ret_data;
}
/* Checks whether user key is unique */
int checkUniqueKey(int key_x) {
struct node *p;
int key_check = FALSE;
for (p = list; p != NULL; p = p->next) {
if (p->key == key_x) {
key_check = TRUE;
break;
}
}
return key_check;
}
You try to cast your address on a position structure instead of a position*
nn=(position)malloc(sizeof(struct node));
Compile your code with gcc flags -Wextra and -Wall to prevent this kind of issue.
Moreover I don't know is it is a mistake but malloc a size of struct node and your nn variable is a pointer on position.
When you initialized your list pointer you set it to NULL(as '\0'), when the program accesses address 0x00 it goes out of its boundaries and the operating system kills the process.
To avoid the segfault you can have "list" of non pointer type thus allocating on stack, when you want to access list as pointer you can do &list. Another solution would involve having variable on stack "root_node" and initialize list pointer as list = &root_node.

C - Segmentation fault - insertion_sort function of linked list

My function insert is not working, after applying some sorting methods that I got at Google (http://teknosrc.com/linked-list-in-c-insertion-sort/).
Firstly, the structures that I'm going to use at it:
// This is the Node , where will be stored the item
struct no
{
Item * item;
struct no *prox;
};
typedef struct no No;
//This is the list, where will have the head node(No)
struct lista
{
char *nomeLista; //This is just a name of the list
No *cabeca; //This is the head node
int tamanho; //This is the amount of items inserted (forgot to implement this)
struct lista *prox; //This is the next list
};
typedef struct lista Lista;
//This is just the main list that will guard all the list of nodes in a linked way. No need to worry about this.
struct vetorListas
{
Lista *cabeca; //head list
int tamanho; //amount of lists
};
typedef struct vetorListas VetorListas;
//This is the item to be inserted
struct item
{
int id; //the ID used for the comparison of sort
char *nome; //just the name of it
};
typedef struct item Item;
In this function, nomeDaList is a string (char *) used to find the list by other function and i is the Item:
void *
insert(void * nomeDaLista, Item * i)
{
Lista * auxLista; //the list
auxLista = idl(nomeDaLista); //the function to get the list by it's name. It works, no worries.
//down here, is the sequence of codes translated to my program (got by the website I showed before)
No * temp = auxLista->cabeca;
No * prev = NULL;
No * ptr;
Item * itemTemp;
itemTemp = temp->item;
ptr = criaNo(i); //this function creates (makes the malloc and all) a node (No) and return the created node.
if(temp == NULL)
{
ptr->prox=NULL;
auxLista->cabeca = ptr;
return auxLista;
}
if(i->id < itemTemp->id)
{
ptr->prox = auxLista->cabeca;
auxLista->cabeca = ptr;
return auxLista;
} else
{
while(temp != NULL)
{
if(i->id > itemTemp->id)
{
prev = temp;
temp = temp->prox;
continue;
} else
{
prev->prox = ptr;
ptr->prox = temp;
return auxLista;
}
}
prev->prox = ptr;
}
}
Please help with this Segmentation fault (core dumped).
You have a check in this line
if(temp == NULL)
which should, and normally would, protect you against segfaults from accessing via NULL pointer.
However, a few lines before, you already dereference the unchecked temp, twice.
itemTemp = temp->item;
and
No * temp = auxLista->cabeca;
You should change the code to make sure that these lines only get executed, if tmp is non-NULL. E.g. split the variable definition and its initialisation and move the init after the check line.
You also receive a pointer from a function criaNo(i) and use it a few lines later, without checking it against NULL.
ptr->prox=NULL;
It is not clear, whether that is guaranteed to be non-NULL. You will have to "rubber-duck" that function, i.e. check in detail, whether it can return NULL.
Here is a nice decription of how to debug (mostly) without a debugger, also explaining "rubber-ducking".
https://ericlippert.com/2014/03/05/how-to-debug-small-programs/
For your problem of not knowing how to use a debugger:
How to debug using gdb?
For your problem of not using an IDE:
Find one, save pain.
My favorite search engine gives (for "free IDE c") my currently used free IDE as first match, the one I am thinking of switching to as third.

Segmentation Fault When Traversing Linked List

I am trying to implement a linked list in C. I believe I am creating and inserting elements correctly, but there is a segmentation fault every time I try to loop through. Here is my code for the linked list:
struct node {
char **data;
struct node *next;
};
Two global variables to store pointers to head and tail:
struct node *head;
struct node *tail;
Code to insert an element:
void insert(char **args)
{
struct node* pointer = (struct node*)malloc(sizeof(struct node));
pointer -> data = args;
pointer -> next = NULL;
if( head == NULL ) {
head = pointer;
tail = pointer;
}
else {
tail -> next = pointer;
tail = pointer;
}
}
I then try to go through the list and print the data contents (this successfully prints the elements in the list, but then there is a segmentation fault):
int print_list(char **args)
{
struct node *curPointer = head;
if(curPointer == NULL) {
printf("%s", "List is empty\n");
}
else {
printf("%s", "List: ");
do {
int i;
while(curPointer->data[i] != NULL) {
printf("%s", tail->data[i]);
i++;
}
printf("%s", "\n");
curPointer = curPointer->next;
}while(curPointer->next != NULL);
}
return 1;
}
Other functions in my program that rely on looping through the list have a similar segmentation fault issue.
The value of local variable i having automatic storage duration is used without initializing, so it will invoke undefined behavior. Initialize i by replacing int i; to int i = 0;
When curPointer becomes NULL in curPointer = curPointer->next;, dereferencing curPointer in the condition curPointer->next != NULL have a big chance to cause Segmentation Fault.
Try using curPointer != NULL instead of curPointer->next != NULL for the condition.

C: pop function in double linked list

I am working with a double linked list and I have run into a problem with my pop() function.
//QueueElement describe the block in the cache
typedef struct _queue_ele_
{
char *content; //the data of the block
struct _queue_ele_ *prev;
struct _queue_ele_ *next;
}QueueElement;
typedef struct _queue_
{
int queue_len;
int max_queue_size;
QueueElement *head;
QueueElement *tail;
}MyQueue;
The pop function works until there is an input of 2 elements ( I clear the queue by poping one by one and freeing the memory)
pop:
// head is removed and returned
QueueElement* pop(MyQueue* myqueue)
{
// if empty
if(myqueue->queue_len == 0) return NULL;
QueueElement *p = myqueue->head;
// if one element
if(myqueue->queue_len == 1)
{
myqueue->queue_len--;
myqueue->head = NULL;
myqueue->tail = NULL;
return p;
}
else
{
myqueue->queue_len--;
//remove the head from the queue
myqueue->head = myqueue->head->prev;
myqueue->head->next = NULL; //******************Seg Fault here
p->prev = NULL;
return p;
}
}
The error I get when there are two elements is a segmentation fault in line shown, but it works for queues with more. Why wont it let me assign NULL to myqueue->head->next???
Change this:
myqueue->head = myqueue->head->prev;
myqueue->head->next = NULL; //******************Seg Fault here
To:
myqueue->head = myqueue->head->prev;
if (myqueue->head != NULL) {
myqueue->head->next = NULL;
}
It is likely that you are trying to dereference a NULL pointer. It also would appear that you may have a memory leak from not calling free on the nodes you are deleting, but it is possible you do that elsewhere in the code.

Resources