I am trying to implement a doubly linked list that acts like a queue (I want it to act like queue).
[EDIT]
When I add nodes to the list (e.g 5 nodes) and empty the list (delete all elements) and try to add another node to the list again, it gives me a segmentation fault (core dumped) error.
linkedlist.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node{
int d;
struct node *prev;
struct node *next;
}node;
typedef struct linkedlist{
int size;
struct node *first;
struct node *last;
}linkedlist;
linkedlist.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "linkedlist.h"
linkedlist* createList(){
linkedlist* myList = (linkedlist*)calloc(1,sizeof(linkedlist));
myList->first = NULL;
myList->last = NULL;
myList->size =0;
return myList;
}
static node* createNode(int n){
node *myNode = (node*)calloc(1,sizeof(node));
myNode->d = n;
myNode->prev = NULL;
myNode->next = NULL;
return myNode;
}
void insertNode(linkedlist* l, int num){
node *temp, *newNode;
newNode = createNode(num);
if (l->size == 0){
newNode->next = NULL;
newNode->prev = NULL;
l->first = newNode;
l->last = newNode;
l->size++;
}
else{
temp = l->first;
while (temp->next != NULL){
temp = temp->next;
}
newNode->prev = temp;
temp->next = newNode;
newNode->next = NULL;
l->size++;
}
}
int deleteNode(linkedlist* l){
node *temp = calloc(1,sizeof(node));
if (l->first ==NULL){
return -1;
}
else if (l->size ==1){
free(l->first);
l->first= NULL;
l->last = NULL;
l->size--;
}
else if (l->size > 1){
temp = l->first;
l->first = temp->next;
free(temp);
}
}
void display(linkedlist *l){
node *temp = calloc(1,sizeof(node));
temp = l->first;
if (temp == NULL){
printf("The list is empty\n");
}
while (temp != NULL) {
printf("-> %d ", temp->d);
temp = temp->next;
}
}
int main(){
linkedlist *myList = createList();
int choice, temp=0, numb;
printf("(1) Insert \n (2) Delete \n");
for (temp; temp<10; temp++){
printf("Choice :");
scanf ("%d", &choice);
switch(choice) {
case 1: {
printf("Enter a Number: ");
scanf("%d", &numb);
insertNode(myList, numb);
display(myList);
break;
}
case 2:{
deleteNode(myList);
display(myList);
break;
}
}
}
}
In your delete node function:
else if (l->size > 1){
temp = l->first;
l->first = NULL; //this is problem
l->first->next = NULL;
temp->next = l->first;
l->first->prev = NULL;
You are assigning l->first = NULL and then accessing it in next statement l->first->next = NULL;, which will fail and give you segmentation fault.
Also, when l->size == 1 you should also set l->first = NULL after freeing it.
The problem appears when access to a "NULL" position. Let's revise the code:
temp = l->first;
l->first = NULL; // here, you set l->first = 0
l->first->next = NULL; // here, you access to 0->next: this is not correct.
temp->next = l->first;
Change it for:
temp = l->first;
l->first = temp->next;
delete temp;
int deleteNode(linkedlist* l){
node *temp= (node*)malloc(sizeof(node)) ;
if (l->first ==NULL){
return -1;
}
else
{
temp= l->first;
l->first= temp->next;
l->first->previous= temp;
l->size--;
free(l->first->previous);
}
}
In the deleteNode you leave first pointing to freed memory if the size is 1
It should be:
else if (l->size ==1){
free(l->first);
l->first = NULL;
l->last = NULL;
l->size--;
}
Also temp is a pointer you don't need to allocate memory for it with malloc
Related
I am trying to compile some c code with multithreading and for some reason I'm getting a segmentation fault in the Ubuntu WSL terminal when I try to run:
gcc -o mashu concurrent_list.c concurrent_list.h
The files I am trying to run are the following:
concurrent_list.c:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "concurrent_list.h"
struct node {
int value;
node* next;
pthread_mutex_t* lock;
// add more fields
};
struct list {
// add fields
node* head;
pthread_mutex_t* lock;
};
void print_node(node* node)
{
// DO NOT DELETE
if(node)
{
printf("%d ", node->value);
}
}
list* create_list()
{
// add code here
list* l = malloc(sizeof(list));
if(l == NULL){
printf("malloc error");
}
l->head = NULL;
l->head->next = NULL;
if(pthread_mutex_init(l->lock, NULL) != 0){
printf("mutex init failed\n");
}
if(pthread_mutex_init(l->head->lock, NULL) != 0){
printf("mutex init failed\n");
}
return l;
}
void delete_list(list* list)
{
// add code here
pthread_mutex_lock(list->lock);
node* head = list->head;
node* next = head->next;
while(next->next != NULL){
free(head);
next = next->next;
head = next;
}
pthread_mutex_unlock(list->lock);
free(list);
}
void insert_value(list* list, int value)
{
// add code here
// if the list is empty
pthread_mutex_lock(list->lock);
if(list->head == NULL){
list->head->value = value;
pthread_mutex_unlock(list->lock);
}
else{
// init newnode
node* newNode = malloc(sizeof(node));
if(!newNode){
printf("malloc failed\n");
}
newNode->value = value;
newNode->next = NULL;
if(pthread_mutex_init(newNode->lock, NULL) != 0){
printf("mutex init failed\n");
}
node* curr = list->head;
// lock the list and the first node
pthread_mutex_lock(curr->lock);
if(curr->next == NULL){ // first and only node at the start of a list
if(curr->value > value){ // insert the newnode at the beggining
list->head = newNode;
newNode->next = curr;
}else{
curr->next = newNode;
}
pthread_mutex_unlock(list->lock);
pthread_mutex_unlock(curr->lock);
// finished the insert
}
else{
node* prev = curr;
curr = curr->next;
pthread_mutex_unlock(list->lock);
pthread_mutex_lock(curr->lock);
while(curr->value < value && curr->next != NULL){
pthread_mutex_unlock(prev->lock);
prev = curr;
curr = curr->next;
pthread_mutex_lock(curr->lock);
}
if(curr->next == NULL){
curr->next = newNode;
}else{
prev->next = newNode;
newNode->next = curr;
}
pthread_mutex_unlock(prev->lock);
pthread_mutex_unlock(curr->lock);
}
}
}
void remove_value(list* list, int value)
{
// add code here
}
void print_list(list* list)
{
// add code here
node* curr = list->head;
pthread_mutex_lock(list->lock);
if(curr != NULL){
pthread_mutex_unlock(list->lock);
while(curr != NULL){
pthread_mutex_lock(curr->lock);
print_node(curr);
curr = curr->next;
pthread_mutex_unlock(curr->lock);
}
}
printf("\n"); // DO NOT DELETE
}
void count_list(list* list, int (*predicate)(int))
{
int count = 0; // DO NOT DELETE
// add code here
printf("%d items were counted\n", count); // DO NOT DELETE
}
int main(){
list* l = create_list();
printf("1\n");
insert_value(l,6);
printf("2\n");
insert_value(l,12);
insert_value(l,3);
insert_value(l,19);
insert_value(l,8);
printf("3\n");
print_list(l);
printf("4\n");
delete_list(l);
}
concurrent_list.h:
typedef struct node node;
typedef struct list list;
list* create_list();
void delete_list(list* list);
void print_list(list* list);
void insert_value(list* list, int value);
void remove_value(list* list, int value);
void count_list(list* list, int (*predicate)(int));
The thrown error when compiling is:
Segmentation fault
Am I accessing illegal memory, not compiling correctly or am I using mutex threads wrong?
Any help would be appriciated.
create_list():
l->head = NULL will segfault if malloc failed. You probably want to return NULL; in addition to the print.
l->head->next = NULL; will always segfault as you set l->head to NULL
pthread_mutex_init(l->head->lock, NULL) will always segfault as l->head is NULL.
insert_value():
list->head->value = value; will segfault if list->head is NULL. You even ensure that it is with the if statement.
As you lock the list on modification (and you need to do that at least for the head changes) I eliminated the node lock. Inlined print_node() in print_list() as the former required caller to take a lock which is risky. Fixed create_list() per above. Simplified delete_list(). Fixed (per above) and simplified insert_value(). Removed dead code remove_value():
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
typedef struct node node;
struct node {
int value;
node *next;
};
typedef struct list list;
struct list {
node *head;
pthread_mutex_t *lock;
};
list* create_list();
void delete_list(list* list);
list *insert_value(list* list, int value);
void print_list(list* list);
list* create_list() {
list* l = malloc(sizeof(*l));
if(!l) {
printf("malloc error");
return NULL;
}
l->head = NULL;
if(pthread_mutex_init(l->lock, NULL) != 0) {
printf("mutex init failed\n");
}
return l;
}
void delete_list(list *l) {
pthread_mutex_lock(l->lock);
while(l->head) {
node *n = l->head;
l->head = l->head->next;
free(n);
}
free(l);
pthread_mutex_unlock(l->lock);
}
list *insert_value(list *l, int value) {
node* newNode = malloc(sizeof(node));
if(!newNode){
printf("malloc failed\n");
return NULL;
}
newNode->value = value;
// head
pthread_mutex_lock(l->lock);
if(!l->head || value < l->head->value){
newNode->next = l->head;
l->head = newNode;
pthread_mutex_unlock(l->lock);
return l;
}
// non-head
node *n = l->head;
for(; n->next && value >= n->next->value; n = n->next);
newNode->next = n->next;
n->next = newNode;
pthread_mutex_unlock(l->lock);
return l;
}
void print_list(list *l) {
pthread_mutex_lock(l->lock);
for(node *n = l->head; n; n = n->next) {
printf("%d ", n->value);
}
pthread_mutex_unlock(l->lock);
printf("\n");
}
int main(){
list* l = create_list();
printf("1\n");
insert_value(l, 6);
printf("2\n");
insert_value(l,12);
insert_value(l,3);
insert_value(l,19);
insert_value(l,8);
printf("3\n");
print_list(l);
printf("4\n");
delete_list(l);
}
and the output is:
1
2
3
3 6 8 12 19
4
I am making a linked list program which utilizes several functions to simplify adding or removing nodes from the list. I believe that my logic is alright with allocating and adding a new node but I am still getting a seg fault. Could you look over my logic and explain what is causing the seg fault? I am very inexperienced with linked lists. Thank you!
This is my function declarations
#define SIMPLELL_H
#include<stdio.h>
#include<stdlib.h>
typedef struct Node
{
int data;
struct Node *next;
}node_t;
node_t* head;
void printList();
void append(int num);
void addFront(int num);
void deleteList();
void removeNode(int num);
int length();
#endif
This is the function definitions
void printList(){
// declare temp to traverse the LL and print each value
node_t *temporary = head;
while(temporary != NULL){
printf("%d, ", temporary->data);
temporary = temporary->next;
}
if (head == NULL){
printf("This list is empty.\n");
}
}
void append(int num){
//declare temporary pointer to traverse LL
node_t *tmp = head;
node_t *prev = NULL;
//malloc the new node
node_t *new = malloc(sizeof(node_t));
if(head == NULL){
//initialize the new node
new->data = num;
new->next = NULL;
head->next = new;
}
else{
//initialize the new node
new->data = num;
new->next = NULL;
//loop to traverse to the last value in the node
while(tmp != NULL){
prev = tmp;
tmp = tmp->next;
}
prev->next = new;
}
}
void addFront(int num){
//allocate memory for new node and allocate local variable equal to head
node_t *new = malloc(sizeof(node_t));
new->data = num;
new->next = head;
head = new;
}
void deleteList(){
node_t *tmp = head;
node_t *prev = NULL;
while(tmp != NULL){
prev = tmp;
tmp = tmp->next
free(prev);
}
}
void removeNode(int num){
//temp is used to traverse the ll until I find the node with the value
//then the previous value is linked to the next value removing the middle value.
node_t *temp = head;
node_t *prev = NULL;
if(head == NULL){
printf("List is not initialized\n");
return;
}
while(temp->data != num){
prev = temp;
temp = temp->next;
if (temp->data == num){
prev->next = temp->next;
free(prev);
}
else{
printf("Value is not in the list\n");
return;
}
}
int length(){
int length = 0;
node_t *temp = head;
while (temp != NULL){
length += 1;
temp = temp->next;
}
return length;
}
This is the driver function which I should not have to change
#include "SimpleLL.h"
#include "SimpleLL.c"
int main()
{
/*head is a global variable*/
head = NULL;
int size =0;
removeNode(1);
append(2);
append(3);
addFront(1);
append(4);
printList();
size = length();
printf("size now %d\n",size);
removeNode(8);
printList();
removeNode(1);
printList();
removeNode(4);
printList();
deleteList();
printList();
size = length();
printf("size after deletion %d\n",size);
return 0;
}
removeNode contains no test for reaching the end of the list. So if the value is not found in the list, it will dereference the NULL pointer at the end and crash.
This will be the case in the very first test, which attempts to remove a node when the list is empty, as well as for removeNode(8).
Your removeNode function also needs to free() the node it removed. Currently it is freeing the node that came after the one removed, which is still in the list and will cause undefined behavior when you access it later.
Hi this is the code I wrote for create as many nodes as he needs (the m variable), but I noticed that using this method I'm creating one more node. What's the best way of fcreating as many nodes as the user say us?
#include <stdio.h>
#include <stdlib.h>
typedef struct Node{
int val;
int rip;
struct Node *next;
} node;
node *modify(node *head);
void print(node *head2);
int main(){
int m, i;
printf("How many nodes: \n");
scanf("%d", &m);
node *head = NULL;
head = (node *)malloc(sizeof(node));
node *temp = head;
node *head2 = NULL;
printf("Write the value in HEAD position : \n");
scanf("%d", &temp->val);
temp->rip=0;
temp->next = NULL;
for(i=0; i < m-1; i++)
{
temp->next = (node *)malloc(sizeof(node));
printf("Write the value in position %d: \n", i);
temp = temp->next;
scanf("%d", &temp->val);
temp->rip=0;
temp->next = NULL;
}
head2 = modify(head);
print(head2);
return 0;
}
node *modify(node *head){
int counter, pass, m;
node *curr = head;
node *track = head;
node *precNode;
while (track != NULL){
counter = 0;
pass = 0;
m = track->val;
while( curr != NULL){
if(m == (curr)->val){
pass++;
counter++;
if(pass > 1){
node *removed = curr;
precNode->next = (curr)->next;
curr = (curr)->next;
free(removed);
}
if(pass == 1)
{
precNode = curr;
curr = curr->next;
}
}
else{
precNode = curr;
curr = (curr)->next;
}
}
track->rip = counter;
track = track->next;
curr = track;
}
return head;
}
void print(node *head2){
while(head2 != NULL){
printf("[%d, %d] -> ", head2->val, head2->rip);
head2 = head2->next;
}
printf("\n");
}
```
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Lists seem really hard for me. I want to find the smallest element in a file: 1 5 8 6 4 8 6 48 9. It's 1 and I want to delete that 1. I can find the smallest element but can not delete it. I find the smallest element place but not the value. I tried copying deleting function from the web, however I cant understand it due to the fact that I'm really new to C. It writes an error that dereferencing to incomplete type. Please help. Post whole code because it should be more convenient to understand.
#include <stdio.h>
#include <stdlib.h>
typedef struct linkedList {
int value;
struct linkedList *next;
} linkedList, head;
linkedList *readList(linkedList *head) {
FILE *dataFile;
dataFile = fopen("duom.txt", "r");
if (dataFile == NULL) {
printf("Nepasisekė atidaryti failo\n");
} else {
printf("Duomenų failą pavyko atidaryti\n");
}
while (!feof (dataFile))
if (head == NULL) {
head = malloc(sizeof(linkedList));
fscanf(dataFile, "%d", &head->value);
head->next = NULL;
} else {
struct linkedList *current = head;
struct linkedList *temp = malloc(sizeof(linkedList));
while (current->next != NULL) {
current = current->next;
}
fscanf(dataFile, "%d", &temp->value);
current->next = temp;
temp->next = NULL;
}
return head;
}
void search(linkedList *head, int *lowest) {
int a[100];
int i = 0;
int minimum;
int b = 0;
linkedList *current = head;
while (current != NULL) {
a[i] = current->value;
current = current->next;
i++;
}
b = i;
i = 0;
minimum = a[0];
while (b > 0) {
if (minimum > a[i]) {
minimum = a[i];
lowest = i;
}
i++;
b--;
}
}
void deleteNode(struct node **head_ref, int key) {
struct node* temp = *head_ref, *prev;
if (temp != NULL && temp->data == key) {
*head_ref = temp->next; // Changed head
free(temp); // free old head
return;
}
while (temp != NULL && temp->data != key) {
prev = temp;
temp = temp->next;
}
if (temp == NULL)
return;
prev->next = temp->next;
free(temp);
}
void printList(linkedList *head) {
linkedList *current = head;
while (current != NULL) {
printf("%d->", current->value);
current = current->next;
}
printf("NULL\n");
return;
}
int main() {
linkedList *A = NULL;
A = readList(A);
search(A);
head = head->next;
minimum = head->value;
headk->next = head->next;
free(head);
printList(A);
return 0;
}
like this
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
typedef struct linkedList{
int value;
struct linkedList *next;
} linkedList, node;
linkedList *readList(void){
FILE *dataFile;
dataFile = fopen("duom.txt", "r");
if(dataFile == NULL) {
perror("file open");
return NULL;
}
int v;
node head = {0, NULL}, *curr = &head;
while (1 == fscanf(dataFile, "%d", &v)){
node *new_node = malloc(sizeof(node));
if(new_node == NULL){
perror("malloc");
break;
}
new_node->value = v;
new_node->next = NULL;
curr = curr->next = new_node;
}
fclose(dataFile);
return head.next;
}
int searchMin(linkedList *head){
if(head == NULL){
fprintf(stderr, "%s: The list MUST NOT be NULL.\n", __func__);
return INT_MIN;
}
int min = head->value;
node *p = head->next;
while(p){
if(p->value < min)
min = p->value;
p = p->next;
}
return min;
}
void deleteNode(node **head_ref, int key){
node *curr = *head_ref, *prev = NULL;
while (curr != NULL && curr->value != key){
prev = curr;
curr = curr->next;
}
if (curr == NULL) return;//not found
if(prev)
prev->next = curr->next;
else
*head_ref = curr->next;
free(curr);
}
void printList(linkedList *head){
node *current = head;
while (current != NULL) {
printf("%d->", current->value);
current = current -> next;
}
puts("NULL");
}
void freeList(linkedList *list){
while(list){
node *temp = list;
list = list->next;
free(temp);
}
}
int main(void){
linkedList *A = readList();
int min = searchMin(A);
printList(A);
deleteNode(&A, min);
printList(A);
freeList(A);
return 0;
}
Please try if this program can help you.
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
struct node {
int data;
struct node *next;
};
void push(struct node **head_ref, int new_data) {
struct node *new_node = (struct node *) malloc(sizeof(struct node));
new_node->data = new_data;
new_node->next = (*head_ref);
(*head_ref) = new_node;
}
void deleteNode(struct node **head_ref, int key) {
struct node *temp = *head_ref, *prev;
if (temp != NULL && temp->data == key) {
*head_ref = temp->next;
free(temp);
return;
}
while (temp != NULL && temp->data != key) {
prev = temp;
temp = temp->next;
}
if (temp == NULL) return;
prev->next = temp->next;
free(temp);
}
void printList(struct node *node) {
while (node != NULL) {
printf(" %d ", node->data);
node = node->next;
}
}
void min(struct node **q) {
struct node *r;
int min = INT_MAX;;
r = *q;
while (r != NULL) {
if (r->data < min) {
min = r->data;
}
r = r->next;
}
printf("The min is %d", min);
deleteNode(q, min);
printf("\n");
}
int main() {
struct node *head = NULL;
FILE *file = fopen("duom.txt", "r");
int i = 0;
fscanf(file, "%d", &i);
while (!feof(file)) {
push(&head, i);
fscanf(file, "%d", &i);
}
fclose(file);
puts("Created Linked List: ");
printList(head);
min(&head);
puts("\nLinked List after Deletion of minimum: ");
printList(head);
return 0;
}
file duom.txt
1 5 8 6 4 8 6 48 9
Test
./a.out
Created Linked List:
9 48 6 8 4 6 8 5 1 The min is 1
Linked List after Deletion of minimum:
9 48 6 8 4 6 8 5 ⏎
Using double pointers first time to create and display linked list
#include "stdio.h"
#include "stdlib.h"
struct node
{
int data;
struct node * next;
};
void Insert(struct node **, int , int );
void display(struct node *);
int main()
{
int c, data, position;
struct node* head;
do{
printf("Enter a choice :\n");
printf("1. Add an element.\n");
printf("2. Del an element.\n3.Display List.\n");
printf("4.Delete linked list.\n5.Exit.\n");
printf("Your Choice :");
scanf("%d",&c);
switch(c){
case 1 :
printf("\nEnter data and position :\n");
scanf("%d %d",&data,&position);
Insert(&head,data,position);
break;
case 2 :
break;
case 3 :
printf("Linked List : \n");
display(head);
break;
case 4 :
break;
case 5 :
exit(0);
default :
printf("Invalid Choice.\n");
break;
}
}while(1);
return 0;
}
void Insert(struct node **ptrhead, int item, int position){
struct node *p,*newnode;
//node creation.
newnode = (struct node *)malloc(sizeof(struct node));
if (!newnode)
{
printf("Memory Error.\n");
return;
}
newnode->next = NULL;
newnode->data = item;
p = *ptrhead;
// Creates initial node
if (!(p->data))
{
p = newnode;
}
// insertion at beginning
if (position==1)
{
newnode->next = p;
p = newnode;
free(newnode);
}
// insertionn at middle or end.
else
{
int i=1;
while(p->next!=NULL && i<position-1){
p=p->next;
i++;
}
newnode->next = p->next;
p->next = newnode;
}
*ptrhead = p;
};
// Display Linked list
void display(struct node *head){
if (head)
{
do{
printf("%d\n", head->data);
head = head->next;
}while(head->next);
}
};
I will add functions for deletion and other operations later. Right now , I just want to insert and display fns to work . But output comes as infinitely running loop with wrong values. I cannot figure out what's wrong in my code , please help ?
Thanks in advance.
Not sure why somebody would be writing this type of C today, looks like maybe I'm doing your homework for you... In any case, you asked to fix your code, not rewrite it, so here's the minimum set of changes.
head should be initialized to NULL.
if (!(p->data)) is not right. That if statement should just be:
// Creates initial node
if (!p)
{
*ptrhead = newnode;
return;
}
Remove free(newnode);.
The insert at middle/end code could be
int i = 1;
struct node *n = p;
while (n->next != NULL && i<position - 1){
n = n->next;
i++;
}
newnode->next = n->next;
n->next = newnode;
The final insert function:
void Insert(struct node **ptrhead, int item, int position)
{
struct node *p, *newnode;
//node creation.
newnode = (struct node *)malloc(sizeof(struct node));
if (!newnode)
{
printf("Memory Error.\n");
return;
}
newnode->next = NULL;
newnode->data = item;
p = *ptrhead;
// Creates initial node
if (!p)
{
*ptrhead = newnode;
return;
}
// insertion at beginning
if (position == 1)
{
newnode->next = p;
p = newnode;
}
// insertionn at middle or end.
else
{
int i = 1;
struct node *n = p;
while (n->next != NULL && i<position - 1){
n = n->next;
i++;
}
newnode->next = n->next;
n->next = newnode;
}
*ptrhead = p;
}
Your print function isn't quite right, just make it:
// Display Linked list
void display(struct node *head)
{
while (head)
{
printf("%d\n", head->data);
head = head->next;
}
}