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
Related
i'm currently writing a program that makes a sorted linked list in C. I'm new to C and am running into errors that I think are based around malloc. I would love if someone can give me some insight on my problems and how to fix them.
These are some of the errors I'm encountering:
==50002==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x563f6970912c bp 0x7ffe5d2b03f0 sp 0x7ffe5d2b03d0 T0)
==50002==The signal is caused by a WRITE memory access.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
int data;
struct node* next;
};
void insert(struct node** n_ref, struct node* newNode) {
struct node* curr;
if (*n_ref == NULL || (*n_ref)->data >= newNode->data) {
newNode->next = *n_ref;
*n_ref = newNode;
} else {
curr = *n_ref;
while (curr->next != NULL && curr->next->data < newNode->data) {
curr = curr->next;
}
newNode->next = curr->next;
curr->next = newNode;
}
}
struct node* makeNode(int num){
struct node* newNode = NULL;
newNode->data = num;
newNode->next = NULL;
return newNode;
}
void delete(struct node** n, int num) {
struct node* temp = *n, *prev;
if (temp != NULL && temp->data == num) {
*n = temp->next;
free(temp);
return;
}
while (temp != NULL && temp->data != num) {
prev = temp;
temp = temp->next;
}
if (temp == NULL) {
return;
}
prev->next = temp->next;
free(temp);
}
void print(struct node* n) {
while (n != NULL) {
printf("%d ", n->data);
n = n->next;
}
}
int duplicate(struct node* n, int num) {
while (n != NULL) {
if (n->data == num) {
return 1;
}
n = n->next;
}
return 0;
}
int main(int argc, char* argv[argc + 1]) {
if (argc < 2) {
return EXIT_SUCCESS;
}
struct node* head = NULL;
FILE *file = fopen(argv[1], "r");
int x;
char str[10];
while (fscanf(file, "%s %d\n", str, &x) != EOF) {
if (strcmp(str, "INSERT")) {
if (duplicate(head, x) == 0) {
struct node* newNode;
newNode = (struct node*)malloc(sizeof(struct node));
newNode = makeNode(x);
insert(&head, newNode);
}
} else if (strcmp(str, "DELETE")) {
delete(&head, x);
}
print(head);
}
fclose(file);
return EXIT_SUCCESS;
}
Sorry for it being so messy. This is my first post here.
The original posted makeNode() assigns a local pointer to NULL and dereferences that 2x. Suggest allocating space and check the result, eg:
struct node* makeNode(int num) {
struct node* newNode;
newNode = malloc(sizeof(*newNode));
if (newNode) {
newNode->data = num;
newNode->next = NULL;
}
return newNode;
}
I have looked at my code several times but couldn't find the problem. please tell me what I need to replace to get my code working.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
struct node
{
int data;
struct node *next;
};
struct node *head;
void insert(int x)
{
struct node *temp=(struct node *)malloc(sizeof(struct node));
temp->data = x;
temp->next = NULL;
if (head == NULL)
{
temp->next = head;
head = temp;
return;
}
struct node *temp1 = head;
while(temp1 != NULL)
{
temp1 = temp1->next;
}
temp1->next = temp;
}
void display()
{
struct node *temp = head;
if (head == NULL)
{
printf("list is empty");
return;
}
else{
while(temp!=NULL)
{
printf("%d ", temp->data);
temp = temp->next;
}
}
}
int main()
{
head = NULL;
insert(3);
insert(5);
insert(6);
display();
}
The problem is in this code:
struct node *temp1=head;
while(temp1!=NULL)
{
temp1=temp1->next;
}
temp1->next=temp;
... the while loop won't end until temp1 is NULL, so after the loop ends, it is guaranteed that temp1 is a NULL pointer ... and then you dereference that NULL pointer (via temp1->next), which causes a crash. Probably what you want to do instead is while(temp1->next != NULL) {...}
while(temp1!=NULL)
{
temp1=temp1->next;
}
temp1->next=temp;
The only way out of this loop is for temp1 to be NULL. Then the next line attempts to used temp1 as a pointer. This is likely causing your issue. You need to instead check if the next is NULL and break leaving temp1 as the last in the list not it's next.
Pro tip for linked lists like this, they are a lot easier to modify with double pointers. Example code:
void append(struct node **list, int a) {
// skip to the end of the list:
while (*list != NULL) {
list = &(*list)->next;
}
*list = malloc(sizeof(struct node));
(*list)->data = a;
(*list)->next = NULL;
}
void display(struct node *list) {
while (list) {
printf("%d\n", list->data);
list = list->next;
}
}
void remove(struct node **list, int index) {
while (*list) {
if (--index == 0) {
struct node *temp = *list;
*list = temp->next;
free(temp);
break;
}
}
}
int main() {
struct list *mylist;
append(&mylist, 3);
append(&mylist, 4);
append(&mylist, 5);
display(mylist); // prints 3 4 5
remove(&mylist, 1);
display(mylist); // prints 3 5
remove(&mylist, 0);
remove(&mylist, 0);
// mylist is NULL again, all memory free'd
}
Note that this code needs no special cases for "is the list empty?", which makes it less complex than yours.
I found this on Internet to reverse a list using recursion and applied it in codeblocks but the output only reverse prints last two Insert call from main function. It skips the first three Insert calls. Why? I did search for this problem here but I failed to understand them as I'm a beginner. Kindly help
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node* next;
};
struct Node * head;
struct Node* Insert (struct Node* head, int data)
{
struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
temp->data = data;
temp->next = NULL;
if(head == NULL)
{
head = temp;
return;
}
struct Node* temp2 = head;
while(temp2->next != NULL)
{
temp2 = temp2->next;
}
temp2->next = temp;
}
void reversePrint(struct Node* head)
{
if(head == NULL)
{
printf("\n");
return;
}
reversePrint(head->next);
printf(" %d ", head->data);
return;
}
int main()
{
struct Node* head = NULL;
head = Insert(head,2);
head = Insert(head,7);
head = Insert(head,3);
head = Insert(head,1);
head = Insert(head,4);
reversePrint(head);
return 0;
}
O/P : 4 1
NOTES:
Don't cast the return of value of malloc
You declared two *head and confused yourself
No need to pass pointer to function and return pointer when you have head declared as global. Which is not a good idea but I followed your code.
Code:
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node* next;
};
struct Node * head;
void Insert (int data)
{
struct Node* temp = malloc(sizeof(struct Node));
temp->data = data;
temp->next = NULL;
if(head == NULL)
{
head = temp;
return;
}
struct Node* temp2 = head;
while(temp2->next != NULL)
{
temp2 = temp2->next;
}
temp2->next = temp;
}
void reversePrint(struct Node* head)
{
if(head == NULL)
{
printf("\n");
return;
}
reversePrint(head->next);
printf(" %d ", head->data);
return;
}
int main()
{
Insert(2);
Insert(7);
Insert(3);
Insert(1);
Insert(4);
reversePrint(head);
return 0;
}
OUTPUT:
4 1 3 7 2
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 ⏎
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