Unusual Seg Fault: Cannot declare variables outside global? - c

I've been stuck for a few hours working on a c program that will loop 5 times while the user inputs 5 integers for a linked list. Somehow I cannot declare variables in my main without getting a segmentation fault in the print function.
My typedef:
typedef struct node_{
int value;
struct node_* next;
}node;
int y = 0; //If this is made local in main, seg fault
My main
int main(void)
{
node *head;
int x;
//int y; /*Does not work here*/
while(y < 5)
{
printf("Insert: ");
scanf("%d", &x);
head = insert_top(head, x);
print(head);
y ++;
}
free(head);
return 0;
}
My insert function
node* insert_top(node* head, int value)
{
node *newHead;
newHead = malloc(sizeof(node));
newHead->value = value;
if(head == NULL)
{
head = newHead;
head->next = NULL;
return head;
}
else
{
newHead->next = head;
head = newHead;
return head;
}
}
My print function
void print(node* head)
{
if(head == NULL)
{
printf("List is empty\n");
return;
}
else
{
while(head != NULL)
{
printf("%d->", head->value);
head = head->next;
}
printf("NULL\n");
}
}
For some reason, if I set the program to loop until the user inputs a number, say, -1, the program is fine and no problem. But I cannot declare any other integers (even if they have no use) without getting a seg fault. Can anyone help me figure out why this is happening and what I can do to fix it? I would like to be led down the path, but not necessarily told the answer.

node *head = NULL;
int y = 0; /*Does not work here*/
Please make above change in main and remove global declaration of y.

Related

Linked List making segmentation fault

Below I have made a simple Linked List in C. The code is currently producing a segmentation fault which I find odd because I was copying an example from our current book. The only thing I did to the code was put the code into the method "addToList". I'm aware the segmentation fault is coming from the method addToList but I do not know where I made a mistake.
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int val;
struct node *next;
} Node;
void addToList(Node *, int);
void printList(Node *);
void main() {
int x;
Node *head = malloc(sizeof(Node));
for (x = 1; x < 4); x++) {
printf("Enter an integer: ");
x = scanf("%d");
addToList(head, x);
}
printList(head);
}
void addToList(Node *head, int val) {
Node *current = head;
while (current->next != NULL) {
current = current->next;
}
current->next = malloc(sizeof(Node));
current->next->val = val;
current->next->next = NULL;
}
void printList(Node *head) {
Node *current = head;
while (current != NULL) {
printf("%d->", current->val);
current = current->next;
}
printf("\n");
}
Any help with telling me what is wrong or where I'm making the mistake would be greatly appreciated.
Look carefully at your code:
int main(void) {
int x;
Node *head = malloc(sizeof(Node));
for (x = 1; x < 4); x++) {
...
addToList(head, x);
}
...
}
You are not initializing the memory, so head->val and head->next are not
initialized. Because of that
while (current->next != NULL) {
current = current->next;
}
will loop an undefined amount of times. The first current->next is most
probably not NULL, so current = current->next get executed. At that point current is pointing to nowhere, hence the undefined behaviour which in your case leads to a segfault.
You have to initialized the memory like this:
Node *head = malloc(sizeof *head);
if(head == NULL)
// error handling
head->next = NULL;
But you could also use calloc, which also sets the memory to 0, thus you don't have to initialize the values (in this case):
Node *head = calloc(1, sizeof *head);
if(head == NULL)
// error handling
You should always check for the return value of malloc/calloc/realloc.
Also note that the signature of the main function can be one of these:
int main(void);
int main(int argc, char **argv);
int main(int argc, char *argv[]);
edit
Another error I've noticed right now:
x = scanf("%d");
That's not how scanf works. You have to pass a pointer, scanf saves the
scanned value through the passed pointer. scanf returns the number of matched
values on success, in this case, success would be 1:
int num;
int ret = scanf("%d", &num);
if(ret != 1)
{
fprintf(stderr, "Could not read value from the user\n");
continue; // to contiune looping
// you could also do a break; and stop the looping, or
// exit(1), etc.
}
// error with scanf
Also don't use the same variable x for the loop iteration and user input,
otherwise you are messing with the loop.
edit
User user3629249 wrote in the comment
good information, however the result will be the first entry in the linked list will contain garbage.
Better to declare head via: Node *head = NULL; and the function addToList() check for NULL and proceed accordingly.
That's right, the head element doesn't save any number in this way.
Option 1: double pointer
Here addToList receives a double pointer. The initialization of head occurs
when *head points to NULL. The function allocates memory for it, initializes
the memory, saves the value and returns. In the concurrent calls of addToList
*head won't be NULL, so addToList looks for the end of the list.
I've made small changes in the way you do malloc and realloc. Also I added
an implementation of freeList which should be used to free the memory:
void addToList(Node **head, int val) {
if(head == NULL)
{
fprintf(stderr, "head cannot be NULL\n");
return;
}
if(*head == NULL)
{
*head = calloc(1, sizeof **head);
head[0]->val = val;
head[0]->next = NULL;
return;
}
Node *current = *head;
while (current->next != NULL) {
current = current->next;
}
current->next = malloc(sizeof *current->next);
if(current->next == NULL)
return;
current->next->val = val;
current->next->next = NULL;
}
int main(void)
{
int x;
Node *head = NULL;
for (x = 1; x < 4; x++)
{
int val;
printf("Enter an integer: ");
if(scanf("%d", &val) != 1)
{
fprintf(stderr, "Could not read from user. Skipping entry\n");
continue;
}
addToList(&head, val);
}
printList(head);
freeList(head);
return 0;
}
void freeList(Node *head)
{
if(head == NULL)
return;
Node *current = head;
Node *next;
while(next = current->next)
{
free(current);
current = next;
}
free(current); // the last one
free(head);
}
Option 2: addToList returns a pointer to the head
Here addToList takes a pointer to the head. If it's NULL, it allocates
memory and initializes like in the shown above. If head is not NULL, the
functions looks for the last element and the returns the head. On error the
function returns NULL.
Node *addToList(Node *head, int val) {
if(head == NULL)
{
head = calloc(1, sizeof **head);
head->val = val;
head->next = NULL;
return head;
}
Node *current = *head;
while (current->next != NULL) {
current = current->next;
}
current->next = malloc(sizeof *current->next);
if(current->next == NULL)
return NULL;
current->next->val = val;
current->next->next = NULL;
return head;
}
int main(void)
{
int x;
Node *head = NULL, *tmp;
for (x = 1; x < 4; x++)
{
int val;
printf("Enter an integer: ");
if(scanf("%d", &val) != 1)
{
fprintf(stderr, "Could not read from user. Skipping entry\n");
continue;
}
tmp = addToList(head, val);
if(tmp == NULL)
{
fprintf(stderr, "Not enough memory\n");
freeList(head);
return 1;
}
head = tmp;
}
printList(head);
freeList(head);
return 0;
}

Linked list — inserting a node at the end

What is wrong in this code. During the insertion operation, when inserting the second element, the programs halts and Windows shows that the program has stopped working. In the build log it shows Process terminated with status -1073741510and sometimes Process terminated with status 255. Even though there's a return statement in the main function.
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
void insert(int);
void print();
struct node
{
int data;
struct node *link;
};
struct node *temp, *temp1, *temp2, *head, *end;
int main()
{
int i, ch, a;
head = NULL;
temp = (node*)malloc(sizeof(node));
printf("Enter the number of items");
scanf("%d", &ch);
for(i = 0; i < ch; i++)
{
printf("\nEnter the number");
scanf("%d", &a);
insert(a);
**call to insert**
print();
}
return 0;
}
void insert(int x)
{
temp = (node*)malloc(sizeof(struct node));
temp->data = x;
temp->link = NULL;
temp2 = head;
if(head == NULL)
{
head = temp;
}
else
{
while(temp2 != NULL)
{
temp2 = temp2->link;
}
temp2->link = temp;
}
}
void print()
{
temp1 = head;
printf("\nthe list is:");
while(temp1 != NULL)
{
printf("%d", temp1->data);
temp1 = temp1->link;
}
}
This part of the function
else
{
while(temp2 != NULL)
{
temp2 = temp2->link;
}
temp2->link = temp;
}
is wrong. After exit from the loop the node temp2 is equal to NULL. Thus this statement
temp2->link = temp;
results in undefined behavior.
Change the code snippet the following way
else
{
while(temp2->link != NULL)
{
temp2 = temp2->link;
}
temp2->link = temp;
}
Also this statement in main
temp = (node*)malloc(sizeof(node));
does not make sense and leads to a memory leak.
These declarations of global variables except of the variable head
struct node *temp, *temp1, *temp2, *head, *end;
also do not make sense.

C Linked List segmentation fault 11

I keep getting this Segmentation Fault: 11 error and I don't know why.
My Code:
typedef struct Node* NodePtr;
struct Node
{
NodePtr next;
void *val;
};
struct List
{
NodePtr head;
};
typedef struct List* ListPtr;
int compare(void *one, void *two)
{
if(*(int*)one < *(int*)two)
return -1;
else if(*(int*)one > *(int*)two)
return 1;
return 0;
}
ListPtr create()
{
ListPtr blah = malloc(sizeof(struct List));
memset(blah, 0, sizeof(struct List));
return blah;
}
NodePtr scan(NodePtr head, void *obj)
{
NodePtr previous, current;
previous = head;
current = head->next; // Segmentation fault here!!
while(current != NULL && (compare(curry->val, obj) == -1))
{
previous = current;
current = current->next;
}
return previous;
}
int insert(ListPtr llist, void *obj)
{
NodePtr newobj = malloc(sizeof(struct Node));
NodePtr prevNode, nextNode;
prevNode = search(llist->head, obj);
nextNode = prevNode->next;
if((nextNode == NULL) || (compare(nextNode->val, obj) != 0))
{
prevNode->next = newobj;
newobj->next = nextNode;
return 1;
}
else
{
free(newobj);
}
return 0;
}
I thought head was not allocated, so I added malloc in create for blah->head, but still no luck.
I think the error is here after some debugging: current = head->next.
Any help would be appreciated! Thank you for your time!
EDIT: How I call insert:
int main(int argc, char *argv[])
{
ListPtr list = create();
int x = 2;
int *p = &x;
while(*p != 0)
{
printf("\nEnter a number: ");
scanf("%d", p);
if(*p != 0)
insert(list, p);
}
return 0;
}
You don’t appear to check whether the list is empty when you scan it. However, without a Minimum Complete Verifiable Example that tells us how you called the function, it is impossible to tell for sure what you did.
Update
Now that you have, that seems to be it. You create an empty list and search it inside your insert function. The search function dereferences the zeroed-out pointer in head, causing a segfault.
Try the following: first, check that your pointer is valid in each of your functions before you do anything with it. An empty list should fail every search. Second, for maximum portability, you want to set your head pointer to NULL (since a NULL pointer is not necessarily all-bits-zero on all implementations).

C - How do I return a pointer value to main?

I have this homework that asks me to make a stack using dynamic allocation and add some different functions in it. Now, usually I would use the head pointer as global variable and make things easier for me, but the homework demands that I give the head pointer to the function as an argument, so I made it local variable in main. This is the code:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int val;
struct node * next;
} node;
void push(int val, node *head) {
node* temp = (node*) malloc(sizeof(node));
node* current = head;
temp->val = val;
if (head == NULL) {
head = temp;
temp->next = NULL;
}
else {
while (current->next != NULL) {
current = current->next;
}
current->next = temp;
temp->next = NULL;
}
}
void print(node *head) {
node* current = head;
if (current->next != NULL) {
while (current->next != NULL) {
printf("%d", current->val);
current = current->next;
}
}
else {
printf("%d", current->val);
}
}
int main() {
node * head = NULL;
int n;
scanf("%d", &n);
push(n, head);
print(head);
push(n, head);
print(head);
push(n, head);
print(head);
}
I get a segmentation fault error at the first print(head) function that says print(head = 0x0), which made me believe that head does not update when it returns in main. I used a printf() for head after the first push function and I was right, head returns 0. Question is: How do I return the updated head in the function?
You could either declare your function like
void push(int val, node **head)
then pass a reference of your head and modify it
or
node *push(int val, node *head)
and return the new head.

SearchListNode Error

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
typedef struct _listnode
{
int item;
struct _listnode *next;
} ListNode;
int search(ListNode *head, int value);
void printList(ListNode *head);
int main()
{
ListNode *head = NULL, *temp = NULL;
int i = 0;
int value = 0;
while (1)
{
printf("Enter a integer: ");
scanf("%d", &i);
if (i == -1)
break;
if (head == NULL)
{
head = malloc(sizeof(ListNode));
temp = head;
}
else
{
temp->next = malloc(sizeof(ListNode));
temp = temp->next;
}
temp->item = i;
}
printList(head);
printf("Enter the value to search for: ");
scanf("%d", &value);
printf("Value of %d found in index %d",value,search(&head, value));
return 0;
}
void printList(ListNode *head)
{
while (head != NULL)
{
printf("%d ", head->item);
head = head->next;
}
printf("\n");
}
int search(ListNode *head, int value)
{
if (head == NULL)
return NULL;
if (head->item != value)
{
head = head->next;
}
return value;
}
I am trying to search a value inside a LinkedList and print out the index of the node when the value is found. But after my printlist, my program just shut down, I did not even reach to the part that require me to enter the value I want to search. Is there something wrong with my printList?
First of all, you should check the return value of scanf() - it returns the number of items successfully matched and assigned. Only after checking the return value can you be sure that the values you use are valid.
The problem, however, is that you never terminate the list properly, that is, you never set the last node's next to NULL. Try to add this after the while:
temp->next = NULL;
Personally, though, I'd advice against doing so. In general, it is more elegant if the list itself is in a consistent state after each iteration of the loop. So, this is what I suggest instead:
while (1)
{
printf("Enter a integer: ");
if (scanf("%d", &i) != 1) {
/* Deal with invalid input... */
}
if (i == -1)
break;
ListNode *new_node;
if ((new_node = malloc(sizeof(*new_node))) == NULL) {
/* Deal with memory exhaustion */
}
new_node->item = i;
new_node->next = NULL;
if (head == NULL)
head = new_node;
else
temp->next = new_node;
temp = new_node;
}
That makes temp work as a pointer to the previous node, so you might want to rename it to prev. Note the check for the return value of scanf() and malloc(), as well as the operand to sizeof: it is a good idea not to hardcode the type when using sizeof for maintenance reasons. Finally, notice, if you will, that there is now a single call to malloc(). This is conceptually easier to understand, since a new node is allocated in the same place in the code, regardless of head being valid or not.
Also, your search() function is broken. It assumes that if value is not the first node's value, then it is the second - not what you want. Also, you are not returning the index of the node, instead, you are returning the value itself. In fact, there's a situation where you return NULL (?!). I doubt that this compiles without warnings.
You need something like this instead:
int search(ListNode *head, int value)
{
int res = 0;
for (; head != NULL && head->item != value; head = head->next, res++)
; /* Intentionally left blank */
if (head == NULL)
return -1;
else
return res;
}
You don't put temp->next to NULL after this line temp = temp->next; in the list creation so it can be NULL or at any other value. When you iterate the list in printList() you reach this random value pointer and you have a segfault.

Resources