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;
}
Related
This question already has an answer here:
Dynamic memory access only works inside function
(1 answer)
Closed last year.
I have a question on which I seek clarity with pointers. I am coming from javascript so I am having a hard time with pointers. I have written singly linked list code mostly by myself and the code is fully working. I have created a function to delete the particular item in the linked list. The function in the main is this:
insertAtMiddle(&head, 3, 500);
insertAtMiddle(&head, 100, 500);
There is one thing I can't understand. First I would like to show the code of my delete function.
void insertAtMiddle(node_t **head, int location, int newData){
node_t *temp = *head;
while(temp->next != NULL){
if (temp->data == location)
{
break;
}
//Shouldn't that also change the original head or move the head to the left as it is passed by reference
temp=temp->next;
}
if (temp->data != location)
{
printf("No location found for replacement!");
}
//Create new node
node_t *newNode = malloc(sizeof(node_t));
newNode->data = newData;
newNode->next = temp->next;
temp->next = newNode;
}
My question is shouldn't the temp=temp->next; inside the while loop should also affect or modify the original head? Head has been passed as a reference to this function. My confusion arises because *temp = *head, temp has been assigned head.
My full code:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} node_t;
void viewAllNodes(node_t *head){
node_t *tmp = head;
printf("\n");
while (tmp != NULL)
{
printf("%d--->", tmp->data);
tmp=tmp->next;
}
printf("\n");
}
void insertAtBegining(node_t **head, int data){
node_t *tmp = malloc(sizeof(node_t));
tmp->data = data;
tmp->next = *head;
*head = tmp;
}
void deleteNode(node_t **head,int data){
node_t *tmp = *head, *nodeToDelete = NULL;
//see two nodes in advance
while(tmp->next != NULL){
if (tmp->next->data == data)
{
nodeToDelete = tmp->next;
break;
}
tmp = tmp->next;
}
if (nodeToDelete == NULL)
{
printf("No node found to delete");
return;
}
tmp->next = nodeToDelete->next;
free(nodeToDelete);
}
void insertAtEnd(node_t **head, int data){
node_t *newNode = malloc(sizeof(node_t));
newNode->data = data;
newNode->next = NULL;
node_t *tmp = *head;
while (tmp->next != NULL)
{
tmp = tmp->next;
}
tmp->next = newNode;
}
node_t *searchNode(node_t *head, int value){
node_t *tmp = head;
while (tmp->next != NULL)
{
if(tmp->data == value){
return tmp;
}
tmp=tmp->next;
}
return NULL;
}
void insertAtMiddle(node_t **head, int location, int newData){
node_t *temp = *head;
while(temp->next != NULL){
if (temp->data == location)
{
break;
}
//Shouldn't that also change the original head as it is passed by
temp=temp->next;
}
if (temp->data != location)
{
printf("No location found for replacement!");
}
//Create new node
node_t *newNode = malloc(sizeof(node_t));
newNode->data = newData;
newNode->next = temp->next;
temp->next = newNode;
}
int main(){
node_t *head = NULL;
insertAtBegining(&head, 1);
insertAtBegining(&head, 2);
insertAtBegining(&head, 3);
insertAtBegining(&head, 4);
insertAtBegining(&head, 5);
insertAtBegining(&head, 6);
insertAtEnd(&head, 8);
insertAtEnd(&head, 9);
insertAtBegining(&head, 100);
viewAllNodes(head);
deleteNode(&head, 1);
deleteNode(&head, 8);
insertAtMiddle(&head, 3, 500);
insertAtMiddle(&head, 100, 500);
viewAllNodes(head);
return 0;
}
You are basically doing this:
#include <stdio.h>
void foo(int* head) {
int temp = *head;
temp = 1234;
}
int main()
{
int bar = 0;
foo(&bar);
printf("bar = %d\n", bar);
}
You expect 1234 as output, but the actual output is 0.
temp is just a local copy, modifying temp will just modify temp and nothing else.
The bubble sort in my code works, but when the program goes to print the newly sorted list I get a segmentation fault.
I print out the swap sequence and it shows that it is correct. The program segmentation faults after the sorting happens and it goes to print the list in order. I'm not sure exactly whats going wrong here.
#include <stdio.h>
#include <stdlib.h>
typedef struct node_t {
int num;
struct node_t *next;
struct node_t *prev;
} node_t;
void add_node (struct node_t **head, int num) {
struct node_t *new = (struct node_t*)malloc(sizeof(struct node_t));
struct node_t *last = *head;
new->num = num;
new->next = NULL;
if (*head == NULL) {
new->prev = NULL;
*head = new;
return;
} else {
while (last->next != NULL) {
last = last->next;
}
last->next = new;
new->prev = last;
}
return;
}
void swap_num(struct node_t **first, struct node_t **second) {
struct node_t *temp;
printf("%d %d\n", (*first)->num, (*second)->num);
temp->num = (*first)->num;
(*first)->num = (*second)->num;
(*second)->num = temp->num;
}
void sort(struct node_t **head) {
int swapped;
struct node_t *temp;
if (*head == NULL){
printf("list is empty...\n");
return;
}
do {
swapped = 0;
temp = *head;
while (temp->next != NULL) {
if (temp->num > temp->next->num) {
swap_num(&temp, &(temp->next));
swapped = 1;
}
temp = temp->next;
}
} while (swapped);
}
void print_list (struct node_t **head) {
struct node_t *temp;
if (*head != NULL) {
temp = *head;
while (temp != NULL) {
printf("%d ", temp->num);
temp = temp->next;
}
printf("\n");
}
}
int main (void) {
struct node_t *head = NULL;
int new_num, x, y, kill;
while (new_num != 0) {
scanf("%d", &new_num);
if (new_num != 0) {
add_node(&head, new_num);
print_list(&head);
}
}
print_list(&head);
sort(&head);
printf("------------------\n");
print_list(&head);
return 0;
}
This seems to be your problem right here:
..\main.c: In function 'swap_num':
..\main.c:40:15: error: 'temp' is used uninitialized in this function [-Werror=uninitialized]
temp->num = (*first)->num;
~~~~~~~~~~^~~~~~~~~~~~~~~
I got this using compile options such as -Wall, -Wextra, and -Werror. If I fix that, your code does not crash. To fix it I just used an int temporary to hold the value instead of a struct node_t*. Here's my revised swap_num() function:
void swap_num(struct node_t **first, struct node_t **second)
{
int temp;
printf("%d %d\n", (*first)->num, (*second)->num);
temp = (*first)->num;
(*first)->num = (*second)->num;
(*second)->num = temp;
}
I am currently writing a program that implements a linked list to maintain a list on integers in sorted order. The program reads the integers from a file in the format of
d [\t] 7
i [\t] 8
i [\t] 7
i [\t] 10
with 'd' meaning delete from the list and 'i' inserting into the list, with no repeat integers allowed. This is the code I have so far:
#include <stdio.h>
#include <stdlib.h>
struct Node{
int data;
struct Node* next;
};
int delete(struct Node** head, int key){
if(head == NULL)
{
return -1;
}
struct Node* ptr = *head;
struct Node* prev = NULL;
while(ptr->data != key && ptr->next!=NULL)
{
prev = ptr;
ptr = ptr->next;
}
if(ptr->data == key)
{
if(prev)
{
prev->next = ptr->next;
}
else
{
*head = ptr->next;
}
free(ptr);
return key;
}
return -1;
}
int insert(struct Node** head, struct Node* newNode){
struct Node* ptr;
if(*head == NULL || (*head)->data >= newNode->data)
{
newNode->next = *head;
*head = newNode;
}
else
{
ptr = *head;
while(ptr->next != NULL && ptr->next->data < newNode->data)
{
ptr = ptr->next;
}
newNode->next = ptr->next;
ptr->next = newNode;
}
return 0;
}
int main(int argc, char* argv[]){
FILE *fp = fopen(argv[1], "r");
int num, found;
char c;
struct Node* head = NULL;
struct Node* ptr = head;
while(fscanf(fp, "%c\t%d\n", &c, &num)!=EOF)
{
for(ptr=head; ptr!=NULL; ptr=ptr->next)
{
if(ptr->data == num)
{
found = 1;
}
}
if(found != 1)
{
if(c == 'i')
{
struct Node *newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->data = num;
newNode->next = NULL;
insert(&head, newNode);
}
}
if(c == 'd')
delete(&head, num);
}
found = 0;
}
for(ptr=head; ptr!=NULL; ptr=ptr->next)
{
printf("%d ", ptr->data);
}
return 0;
}
It works fine when the first letter is 'i', but whenever the first letter is 'd' I get a segmentation fault. Why is this?
When you try to delete a node first thing you do, the list is empty and inside the delete function *head (notice the dereference!) is a null pointer.
Since *head is a null pointer, so will ptr be, and you then dereference ptr without checking for that.
You might want to modify the initial check to be head == NULL || *head == NULL.
whenever the first letter is 'd' I get a segmentation fault.
If the first letter is D, your list is still empty when you call delete.
In your first if, you need to dereference your pointer, as #SomeProgrammerDude mentionned.
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 ⏎