Segmentation Fault in Linked List C program - c

I am trying to create a list of 10 Nodes and assigning with the values 1 to 10 and printing them. I tried it with the following code, but I am ending up with segmentation fault.
I am very new to Linked Lists in C.
#include<stdio.h>
typedef struct Node
{
int data;
struct Node *next;
}Node_Struct;
int main(void)
{
int i =0;
Node_Struct* Node = NULL;
Node = (Node_Struct*)malloc(sizeof(Node_Struct));
for (i = 1; i<=10; i++){
Node->data = i;
Node = Node->next;
}
for (i = 1; i<=10; i++){
printf("\n Node->data:%d",Node->data);
Node = Node->next;
}
return 0;
}

As pointed by people in comments, you're only allocating memory to head node only. You need to allocate memory for each node you're trying to add int that for loop also. Moreover you're moving on the Node pointer forward at each iteration, so you won't be able to traverse list after insertion. Keep a track of both head and tail of the list. Do the following:
Maintain head and tail of linked list:
Node_Struct* headNode = NULL, *tailNode = NULL;
// head node
headNode = tailNode = (Node_Struct*)malloc(sizeof(Node_Struct));
Allocate memory at each iteration in the loop. It's your wish whether you want to keep something in head node or not. So change the code in for loop like this:
for (i = 1; i<=10; i++) {
Node_Struct* newNode = (Node_Struct *)malloc(sizeof(Node_Struct));
newNode->data = i;
newNode->next = NULL;
tailNode->next = newNode;
tailNode = newNode;
}
After this you can iterate your list by copying head value in some other variable:
Node_Struct *tmpNode = headNode;
for (i = 1; i<=10; i++){
printf("\n Node->data:%d",tmpNode->data);
tmpNode = tmpNode->next;
}

You are not allocating memory for each added node.
If to use your loops then it is enough to make these minor changes
Node_Struct* Node = NULL;
Node_Struct **current = &Node;
for (i = 1; i <= 10; i++ ) {
*current = malloc(sizeof(Node_Struct));
(*current)->data = i;
(*current)->next = NULL;
current = &(*current)->next;
}
current = &Node;
for (i = 1; i <= 10; i++) {
printf("\n Node->data:%d", ( *current )->data);
current = &( *current )->next;
}
Take into account that you should free all allocated memory for the nodes before exiting the program.

You have allocated space for just a single node, yet you are trying to loop over a list of linked nodes by doing this:
for (i = 1; i<=10; i++){
Node->data = i;
Node = Node->next;
}
When you do this - Node = Node->next;, Node might point to anywhere. You might be pointing to memory you are not supposed to touch.
One thing to remember is never to let go of the handle to the head of the list. Keep a pointer to the head of the list by maintaining a copy.
Node = malloc(sizeof(Node_Struct));
Node_Struct *head = Node;
Allocate space for each node by using malloc(). Build up the list of nodes first. One way to do that is like this:
for (i = 1; i<=10; i++){
Node->next = malloc(sizeof (Node_Struct));
Node = Node->next;
}
Node->next = NULL // The last node should point to NULL
After that you could set all the data field of the nodes in another loop or, set them in the same loop while doing malloc(). As you already have the handle to the head of the list, you know where to start. Like so:
Node = head;
i = 0;
while (Node) {
Node->data = i++;
Node = Node->next;
}

First I am showing you where your mistakes are and below I have re-written you code to fix your problem. See my codes and compare with yours. Hope that will help you to learn data structure.
Let’s see you mistakes
#include<stdio.h>
typedef struct Node
{
int data;
struct Node *next;
}Node_Struct;
int main(void)
{
int i =0;
Node_Struct* Node = NULL;
Node = (Node_Struct*)malloc(sizeof(Node_Struct));
for (i = 1; i<=10; i++){
Node->data = i;/* till here everything fine */
Node = Node->next; /* now you are pointing to nowhere */
/* in the next iteration of for loop Node->data = i will crash the application */
/* you could have done it like below
Node->next = (Node_Struct*)malloc(sizeof(Node_Struct));
Node = Node->next;
Node->data = i;
Node->next = NULL
but here you lost the address of first node so all gone*/
}
for (i = 1; i<=10; i++){
printf("\n Node->data:%d",Node->data);
Node = Node->next;
}
return 0;
}
Now see my code below
int main(void)
{
int i =0;
Node_Struct *Node = NULL;
Node_Struct *p = NULL;
for (i = 1; i<=10; i++){
if ( Node == NULL )
{
Node = (Node_Struct*)malloc(sizeof(Node_Struct));
Node->data = i;
Node->next = NULL;
p = Node; /* p is pointing to the first Node of the list */
}
else
{
p->next = (Node_Struct*)malloc(sizeof(Node_Struct));
p = p->next;
p->data = i;
p->next = NULL;
}
}
p = Node; /* now p is pointing to first node of the link list */
/* if you see above we always assign NULL to 'next' pointer so that the last node of the list pointing to NULL */
/* Therefore in the below while loop we are searching the list untill we reach the last node */
while( p != NULL )
{
printf("\n p->data:%d",p->data);
p = p->next;
}
return 0;
}

Related

Segmentation fault error while freeing the memory

I tried to make a self-made program for lists. So, I created some basic stuff like creating the list, adding new nodes, showing them, and deleting all the existing nodes in the list.
However, when I put in my list more than 27 elements, it throws me a segmentation fault error while freeing the memory. By the way, when I add like 26 or smaller number of them, it works great. Maybe stack is overflowed or something like that, I really have no idea.
P.S don't tell me that I`m developing a bike, in this way, making something by myself first, I understand things better:)
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
typedef struct node{
struct node * next;
int value;
} node;
int addNode(int position,int value, node ** head,int * size){
int i = 2;
node * curNode = *head;
if(position > *size) return;
while(i <= *size){
if(position == 1){
node * adress = *head;
*head = (node*) malloc(sizeof(node*));
(*head)->next = adress;
(*head)->value = value;
break;
}
else if(i == position){
node * adress = curNode->next;
curNode->next = (node*) malloc(sizeof(node*));
curNode = curNode->next;
curNode->next = adress;
curNode->value = value;
break;
}
else{
curNode = curNode->next;
++i;
}
}
++(*size);
return;
}
void showList(node * head, int size){
int i; node * currentNode = head;
for(i = 0; i < size; ++i){
printf(" %d , next adress: %p |\n", currentNode->value, currentNode->next);
currentNode = currentNode->next;
}
printf("\n");
}
void cleanList(node * head, int size){
int i;
node * curNode = head; node * nextToDelete = NULL;
for(i = 0; i < size; ++i){
nextToDelete = curNode->next;
free(curNode);
curNode = nextToDelete;
}
}
int main() {
node * head = (node*) malloc(sizeof(node*)); //saving head adress to know where the list starts
head->value = 1; //set head value as "1"
int i, size;
node * currentNode = head; //pointer which points to a current node
for(i = 0; i < 5; ++i){
node * adress = (node*) malloc(sizeof(node*)); //variable which saves new node`s adress
currentNode->next = adress; //set this new nod`s adress to previous node`s "next" parametr
currentNode = adress; //set new node`s adress to a current node
currentNode->value = i+2; ///set value for this node
}
size = 6;
addNode(2, 15, &head, &size);
showList(head, size);
showList(head, size);
cleanList(head, size);
return 0;
}
You are allocating memory incorrectly.
Notice these lines:
*head = (node*) malloc(sizeof(node*));
and
curNode->next = (node*) malloc(sizeof(node*));
You are allocating memory for a pointer to struct node instead of the actual struct.
Notice the sizeof function - you pass it the wrong parameter!
Your structure contains an int and a pointer. Those are usually the same size.
But you only allocate memory for a pointer, so, you allocate half the structure.
This will cause you to call free on an invalid address at some point.
It is a miracle your program only crashed during free operation, it should have crashed much sooner.

Creating Linked List in C using for loop for assigning values

I am trying to create a linked list for my program using a for loop which assigning values. In the creation of this linked list, I want to be able to keep track of the head and have the first value in the for loop assigned to the head. For example, if I am creating a list from 0 to n - 1, I want the head to point to 0 and the rest of the list to be followed by 1-2-3-4-...-n-1. I have programmed a loop that does just that, however, the for loop has to count down backward instead of forward. Here is my code:
// Structure
typedef struct node {
int value;
struct node * next;
} ListNode;
int size = "some value";
ListNode * head = NULL; // beginning of the linked list
ListNode * temp; // temporary node
for(int count = size - 1; count >= 0; count--)
{
// creates temporary nodes //
ListNode * tempNode = malloc(sizeof(ListNode));
tempNode -> value = count;
tempNode -> next = NULL;
// creation of node completed
temp = tempNode;
temp -> next = head;
head = temp;
}
Although in this program the head points to 0 as I intend, is there a way to have the for loop start from 0 all the way up until n and still produce the same output. I would like it to look like (int for count = 0; count < n; count++). It is just a preference thing that I was wondering was possible. Please help if you know, thank you!
First, in your code, you don't need the extra tempNode, just use temp and make it local to the inner block:
for (int count = size; count--; ) {
ListNode *temp = malloc(sizeof(*temp));
temp->value = count;
temp->next = head;
head = temp;
}
If you want to append elements at the end, you should keep a pointer to the last node, the tail:
ListNode *head = NULL;
ListNode *tail = NULL;
for (int count = 0; count < size; count++) {
ListNode *temp = malloc(sizeof(*temp));
temp->value = count;
temp->next = NULL;
if (tail == NULL) {
head = temp;
tail = temp;
} else {
tail->next = temp;
tail = temp;
}
}
There is a more elegant way to do this: Instead of keeping a pointer to the last node, keep a pointer to the null pointer where the next element should go:
ListNode *head = NULL;
ListNode **tail = &head;
for (int count = 0; count < size; count++) {
ListNode *temp = malloc(sizeof(*temp));
temp->value = count;
temp->next = NULL;
*tail = temp;
tail = &(*tail)->next;
}
At the beginning, *tail holds the address of head, after that it will hold the address of the next member of the last node. You can update both via the pointer tail without the need to check whether the list is empty or not.
This last method looks a bit daunting at first with its ListNode **tail, but once you get the hang of it, it's a useful tool to have. If you don't feel comfortable with it (yet), use the first variant.
Is it worth the effort only to create the list forwards? Insertion to a list at the front is easy and after tidying up, your original variant looks clean and compact to me.

How to implement a [copy array to linked list] function?

What this supposed to do is:
Create an array with 4 elements.
Print these 4 elements.
Copy array elements to a created linked list in copy fucntion.
Print linked list with print and traverse fuction.
I tried this and it compiles, but crashes after printing the array.
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define ELEMENTS 4
struct node {
int data;
struct node *next;
};
struct node *head;
void insert(int x) {
struct node *temp = malloc(sizeof(struct node));
temp->data = x;
temp->next = NULL;
if (head != NULL)
temp->next = head;
head = temp;
}
void copy(struct node *head, int array[ELEMENTS], int n) {
//copying array elements and create linked list
struct node *temp = malloc(sizeof(struct node));
temp->data = array[0];
temp->next = NULL;
head = temp;
int i;
for (i = 1; i < n; i++) {
struct node *temp2 = malloc(sizeof(struct node));
temp->next = temp2;
temp2->data = array[i];
temp2->next = NULL;
temp = temp2;
}
}
void printlist() {
struct node*temp = head;
printf("List is : ");
while (temp->next != NULL) {
printf(" %d ", temp->data);
temp = temp->next;
}
printf("\n");
}
int main() {
int *array = (int*)calloc(ELEMENTS , sizeof(int));
int i = 0;
for (i = 0; i < ELEMENTS; i++) {
printf("arrays = [%d] ", i);
scanf("%d", &array[i]);
}
for (i = 0; i < ELEMENTS; i++)
printf("array [%d] = %d \n", i, array[i]);
copy(head, array[ELEMENTS], ELEMENTS);
printlist();
getchar();
return(0);
}
How to fix it?
You dont need to pass head to the copy function because it is global and when you do you create a local pointer named head which gets destroyed as soon as function is over.
So copy should look like this
void copy(int array[ELEMENTS],int n) //copying array elements and create linked list
{
struct node*temp = malloc(sizeof(struct node));
temp->data=array[0];
temp->next=NULL;
head =temp;
int i;
for(i=1;i<n;i++)
{
struct node*temp2= malloc(sizeof(struct node));
temp->next= temp2;
temp2->data = array[i];
temp2->next = NULL;
temp=temp2;
}
}
Also while printing change while to
while(temp!=NULL)
{
printf(" %d ",temp->data);
temp=temp->next;
}
When you call the function copy, you are passing "array[ELEMENTS]" as an argument, but you want to pass only "array". What you're passing is value after your array, which the copy function is trying to interpret as an address of an array it's actaully expecting.
Note that accessing a value that is not yours like this results in undefined behaviour and can actually make the system kill your application. But what probably happened after is there will be a 0 in the memory, which gets passed to the copy function and it then tries to access values at memory 0x0 to 0xF, which almost always results in segmentation fault, which as you experienced first hand, causes the program to stop working.
Bottom line, delete [ELEMENTS] at the line where you call the copy function and I believe the program should start working. I implore you though to do further research on pointers and passing them as function parameters.
(And since I cannot comment yet I will just put this in here, as Sniper stated, you don't have to pass reference to global variable, but he is wrong about the structure being destroyed at the end of the function. That would have been true, if it was created at stack, but you are allocating space for it at heap, which means it will stay there until you either free() it or the program ends.)
I have simple dimple answer:
#include<stdio.h>
#include<stdlib.h>
struct Node{
int current;
struct Node *next;
};
struct LinkedList{
struct Node *head;
};
int main(){
int i, data[5] = {10, 20, 30, 40, 50};
struct Node *node = malloc(sizeof(struct Node));
struct LinkedList *llist = malloc(sizeof(struct LinkedList));
node->current = data[0];
node->next = NULL;
llist-> head = node;
for(i = 1; i <= sizeof(data) / sizeof(data[0]) - 1; i++){
struct Node *new_node = malloc(sizeof(struct Node));
node->next = new_node;
new_node->current = data[i];
new_node->next = NULL;
node = new_node;
}
node = llist->head;
printf("llist: ");
while(node != NULL){
printf("%d->", node->current);
node = node->next;
}
return 0;
}

Returning a pointer to the beginning of a linked list after adding nodes?

struct node {
struct node *next;
int num;
} Node;
Node *insert(int i) {
Node *head;
for (int c = 0; c < i; c++) {
head = malloc(sizeof(Node));
head.num = i;
head = head->next;
}
}
The insert function is supposed to create a linked list and add numbers from 0 to i to that linked list. However, it is also supposed to return a pointer to the beginning of the list/the list itself and I can't seem to figure out how to do it. I've tried to make a pointer and set it equal to head after adding the first node, but it only returns the first node and not the entire list. Can someone please help? Thanks.
You probably want to remember the previous node, so you can assign its next pointer. When you add a node, set its next pointer to the old head, and it now becomes the new head of the list. Which you can just return after the last iteration of the loop.
Node *insert(int i) {
Node *head, *prev = NULL;
for (int c = 0; c < i; c++) {
head = malloc(sizeof(Node));
head->num = i;
head->next = prev;
prev = head;
}
return head;
}
Update: to insert each new element at the end of the list, you need a bit more bookkeeping:
Node *insert(int i) {
Node *last_node = NULL;
Node *first_node = NULL;
for (int c = 0; c < i; c++) {
Node *node = malloc(sizeof(Node));
node->num = i;
node->next = NULL;
if (!last_node) {
// Remember the first node, so we can return it.
first_node = node;
}
else {
// Otherwise, append to the existing list.
last_node->next = node;
}
last_node = node;
}
return first_node;
}
It is as simple as introducing another variable. You currently have head to track the head of the list; add another to track the tail of the list:
struct node {
struct node *next;
int num;
} Node;
Node *insert(int i) {
Node *head;
Node *tail;
head = malloc(sizeof(Node));
head.num = 0;
tail = head;
for (int c = 1; c < i; c++) {
// allocate a new node at the end of the list:
tail->next = malloc(sizeof(Node));
// set "tail" to point to the new tail node:
tail = tail->next;
tail->num = c;
}
return head;
}
You could also add a special case for i == 0, if necessary.
By the way - and I realise this is possibly a task given to you as an exercise - but insert is a terrible name for a function that actually creates and fills an entirely new list.

Getting input into a linked list using a loop

I made this program to learn about linked lists as I am just starting out with them. The program terminates immediately after the statement "Enter the amount of pesticide"(it is a school assignment). Also, I am unsure how do I keep the length of the list limited to the size input by the user.
#include<stdio.h>
struct plants{
int val;
struct plants *next;
};
void printlist();
int main(){
struct plants* head = NULL;
struct plants* current= head;
head = malloc(sizeof(struct plants));
int counter,size;
printf("Enter the number of plants\n");
scanf("%d",&size);
printf("Enter the amount of pesticide each plant has.\n");
while(current!=NULL){
scanf("%d",current->val);
current= current->next;
}
return 0;
}
#include<stdio.h>
#include<malloc.h>
int main()
{
int count = 0;
int size = 0;
printf("Enter the number of plants\n");
scanf("%d",&size);
printf("Enter the amount of pesticide each plant has.\n");
You have to allocate the memory for each node inside the while loop. If you like to add the new node at the end of the list notice the end of the list by a pointer to the pointer at the end of the list. Apart form this you have to pass the addres of the value to be read to scanf:
struct plants * head = NULL;
struct plants ** current = &head; // current refers there, where next node has to be placed
while( count < size ) // do it for "size" nodes
{
*current = malloc(sizeof(struct plants)); // allocate memory for the node right to target
scanf( "%d", &((*current)->val)); // read the data
(*current)->next = NULL; // node is last node in list, so its successor is NULL
current = &((*current)->next); // step on forward
count ++; // increment number of nodes
}
Note since the type of current is struct plants ** this codes puts the new node to head for the first element of the list and to (*current)->next for all further nodes of the list.
It would be easier to add the new node at the head of the list:
struct plants * head = NULL; // init head with NULL (this becomes end of the list)
while( count < size ) // do it for "size" nodes
{
struct plants * current = malloc(sizeof(struct plants)); // allocate memory for the node
scanf( "%d", &current->val); // read the data
current->next = head; // successor of node is head
head = current; // new node is head of list
count ++; // increment number of nodes
}
This will print your list:
struct plants *temp = head;
while( temp != NULL )
{
printf( "%d ", temp->val );
temp = temp->next;
}
Don't forget to free the list at the end of your program:
while ( head != NULL )
{
struct plants *next = head->next;
free( head );
head = next;
}
return 0;
}
struct plants* head = malloc(sizeof(struct plants));//declare an initialize in memory
struct plants* current= head;
int i = 0;
struct plants* aux = NULL;
while(i ++ < size)
{
aux = malloc(sizeof(struct plants)); // used for new values
scanf("%d", aux->val);
aux->next = NULL;
current->next = aux;
current = aux;
}
Loop while you have less than the quantity required by user. Use an auxiliar node. Read the value, set the current next position to the aux node, the aux node to null and set the current node to aux to be sure you are at the last node from the list.
Lot of things to be corrected, check for the code below. and should be pretty easy for a beginner to understand. I haven't changed the format of your code for ease of understanding
#include<stdio.h>
#include<stdlib.h>
struct plants{
int val;
struct plants *next;
};
void printlist();
int main(){
int i;
struct plants* head = NULL,*temp=NULL;
struct plants* current= head;
int counter,size;
printf("Enter the number of plants\n");
scanf("%d",&size);
printf("Enter the amount of pesticide each plant has.\n");
for(i=0;i<size;i++){
temp = malloc(sizeof(struct plants));
scanf("%d",&temp->val);
temp->next=NULL;
if(head==NULL)
{
head=temp;
current=head;
}
else
{
current->next=temp;
current=temp;
}
}
current = head;
while(current!=NULL){
printf("%d\t",current->val);
current= current->next;
}
}

Resources