Reputation: 39
I write a very basic linked list in C supporting only two operations - insert of a node to the top of the list and iterate over the list in order to print the value of each node. The problem I am facing is that I have a segmentation fault when executing. Here is my code:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct linkedList
{
int data;
struct linkedList *next;
};
struct linkedList* createNode(int value)
{
struct linkedList *node;
node = malloc(sizeof(struct linkedList));
node->next = malloc(sizeof(struct linkedList));
node->next = NULL;
node = NULL;
return node;
}
//insert a node at the top of the linked list
struct linkedList* insertTop(struct linkedList* top,struct linkedList* node)
{
if(top == NULL)//the element we insert is the 1st element for the linked list
{
node->next = NULL;
//the first element points to NULL since it has no successors
}
else//there is already an element in the list
{
node->next = top;
}
return node;
}
void iterate(struct linkedList* top)
{
while(top->next != NULL)
{
printf("Data = %d\n", top->data);
top = top->next;
}
}
int main()
{
struct linkedList *a,*b,*c,*root;
a = createNode(2);
b = createNode(10);
c = createNode(23);
root = insertTop(NULL,a);//these 3 lines provoke a segmentation fault
root = insertTop(root,b);
root = insertTop(root,c);
iterate(root);//the result I expect here is 23,10,2
return 0;
}
I know this question has been asked many times on stackoverflow and yet I still can't figure out why my code does not work as expected. Can you please explain to me where is the problem and how can I fix it? Thank you
Upvotes: 1
Views: 541
Reputation: 223872
There are two main issues. First createNode
:
You allocate space for a struct linkedList
and assign it to node
, which is good. But then you do the same for node->next
. So you're actually creating two nodes, but then you set node->next
to NULL ,loosing the reference to the second bit of memory you allocated, creating a memory leak. The same happens when you do the same for node
. The end result is that you always return NULL for your new node. Also, you don't assign value
to anything.
Just do the first allocation, assign value
to data
, and initialize next
to NULL:
struct linkedList* createNode(int value)
{
struct linkedList *node;
node = malloc(sizeof(struct linkedList));
node->data = value;
node->next = NULL;
return node;
}
The next issue is in iterate
:
while(top->next != NULL)
This causes the iteration to stop when the current node is the last one, so you don't print the last node. Also, as a result of how createNode
was originally implemented, your root
pointer is NULL, so you end up dereferencing a NULL pointer, which causes a core dump.
You want to test if top
is NULL instead:
while(top != NULL)
A third issue is cleanup. You need to define a function to free
the memory you allocated before your program exits. You can do that like this:
void cleanup(struct linkedList *top)
{
struct linkedList *temp;
while (top != NULL) {
temp = top;
top = top->next;
free(temp);
}
}
Upvotes: 3
Reputation: 210918
If you like to create a node you only have to allocate mamory for one node. Adapt your code like this:
struct linkedList* createNode(int value)
{
struct linkedList *node = malloc(sizeof(struct linkedList));
node->next = NULL;
node->data = value;
return node;
}
Apart from this you have to change the termination condition of the while
loop in your function iterate
:
void iterate( struct linkedList *top )
{
while( top != NULL) // if to is not NULL you can print its data
// ^^^
{
printf("Data = %d\n", top->data);
top = top->next;
}
}
And you can simplify your function insertTop
:
struct linkedList* insertTop(struct linkedList* top,struct linkedList* node)
{
if( node == NULL ) // test if node is not NULL
return top;
node->next = top; // successor of new node is top (top possibly is NULL)
return node;
}
Dont't forget to free
your list at the end of main
:
int main()
{
struct linkedList *root = NULL;
root = insertTop( root, createNode(2) );
root = insertTop( root, createNode(10) );
root = insertTop( root, createNode(23) );
iterate(root);
while ( root != NULL )
{
struct linkedList *temp = root;
root = root->next;
free( temp );
}
return 0;
}
Apart from this you can combine createNode
and insertTop
to one function createTop
:
struct linkedList* createTop( struct linkedList* top, int value )
{
struct linkedList *node = malloc(sizeof(struct linkedList));
node->next = top;
node->data = value;
return node;
}
Upvotes: 1
Reputation: 12270
You have quite a few problems there..
In the function createNode()
you are allocatting memory to node
and then throwing it away by doing node = NULL
.
Loose those statements, as they create a memory leak.
struct linkedList* createNode(int value)
{
struct linkedList *node;
node = malloc(sizeof(struct linkedList));
node->data = value;
node->next = NULL;
return node;
}
Upvotes: 0
Reputation: 399813
This:
node = NULL;
doesn't look so good in the createNode()
function. In fact, that entire function doesn't look so good. It should be something like this:
struct linkedList* createNode(int value)
{
struct linkedList *node = malloc(sizeof *node);
node->next = NULL;
node->data = value;
return node;
}
It really shouldn't have been allocating more than one node, that's not sane.
Upvotes: 3