Segmentation Fault 11 with ANSI C Linked List - c

Updated with some new details:
Interestingly if I get no segfault if I don't use: node->next = NULL. I can create the nodes fine, but it seems there's an issue in setting the initial list head to my new node, as well as dereferencing ->next.

Note that without the structure definitions, it make be a bit harder for us to know what is wrong...
You have a problem here where you use the allocated pointer before testing whether the malloc() failed. Although that's probably not the culprit at this point.
struct node *head = (struct node*)malloc(sizeof(struct ftt_node));
foodList->head = head; // <<<---- here using the pointer NULL or not
head->next = NULL;
rest->foods = foodList;
if (NULL == rest->foods) { // <<<---- testing here if malloc() failed
printf("List creation failed");
return FALSE;
}
As a side note, the head pointer has the same problem.
Then in add_node you do that, with newNode never allocated... so probably garbage!
struct node *newNode;
newNode->data = newFood;
You probably wanted to allocate newNode and use curr to find the last existing node.
Something like this:
void add_node(POS * POS, struct food * newFood)
{
struct node *newNode;
struct node *newNode = (struct node*)malloc(sizeof(struct node));
newNode->data = newFood;
curr = POS->foods->head;
while (curr != NULL)
{
curr = curr->next;
}
curr->next = newNode;
newNode->next = NULL;
}
That being said, I would very strongly suggest that you create a base list object with functions to handle the list, and then start your node with that list, instead of writing it this way.
As a side note: You should NOT name the variable POS in your add_node(). That's bad practice as it shadows your variable type.
Just wondering, why not use C++? At least testing for NULL is not required because new throws if memory cannot be allocated... And for list you have std::list, although in your case std::vector would probably work better so you could go through your array of nodes with a very simple for().

Your newNode variable in add_node is unitialised so it can point anywhere in memory, which can be the cause of the segfault when you try to dereference it on the second line. In addition, you allocated a new struct node structure but overwrote its adress immediately. So your first few lines should be rewritten thus:
struct node *newNode = (struct node*)malloc(sizeof(struct node));
newNode->data = newFood;
struct node *curr = POS->foods->head;

The add_node() function never modifies pos->foods->head. It also never initializes new_node, so that pointer cannot be dereferenced without triggering undefined behavior.
Thus, the list can never grow from being empty.

Related

Double Linked List Crashing After Appending Node

I am trying to achieve a double linked list using C and have encountered a crash whenever I try to append a third node to my list. I have located the line in my code in which my program crashes, but I cannot understand why since the code looks "safe". I have received no warnings or errors from the compiler. If anyone is able to explain a possible pointer error or the reason behind the crash, it would be much appreciated. Any questions or concerns related to my code will be answered as soon as I see them.
struct node *appendNode(struct node *headRef, unsigned short int newData) {
struct node *newNode = (struct node*)malloc(sizeof(struct node*));
newNode->data = newData;
newNode->next = NULL;
if(headRef == NULL) { //list is empty and returns the newNode to become the head pointer
newNode->previous = NULL;
return newNode;
} else { //list is not empty and newNode is appended to end of list ----(Area of crash)----
struct node *current = headRef;
while(current->next != NULL) {
current = current->next;
}
current->next = newNode;
newNode->previous = current;
return headRef;
} //----------------------------------------------------------------------------------
};
The code presented above is a function that appends a new node to the list. It returns a new address or same address back when finished to update the head pointer used in 'main'. The code runs functionally whenever I append the first two nodes, but crashes whenever it tries to append a third node.
The amount of memory space you are allocating is the size of a pointer to a struct node, not the actual size of a struct node - which you want.
So it should be
struct node *newNode = (struct node*)malloc(sizeof(struct node));
As a consequence of allocating insufficient memory, your program is writing outside the memory block that it allocated, which causes undefined behavior. This means that anything can happen. For example, the program may crash immediately, not at all, or at a later time.

program in c runs into infinite loop when I use free()

I was trying out a linked list program in c where I use malloc() to allocate memory dynamically and then when I tried using free() at the end of the function, the program runs into an infinite loop.
Why is this happening ?
void Insert(int x, int pos)
{
struct Node *newnode = (struct Node*) malloc(sizeof(struct Node));
newnode->data = x;
newnode->next = NULL;
struct Node* temp, *left, *right;
int i = 1;
temp = head;
if(head == NULL)
{
head = newnode;
}
else{
while(i != pos - 1)
{
temp = temp->next;
i++;
}
newnode->next = temp->next;
temp->next = newnode;
}
free(newnode);
}
You use free() in the wrong place, resulting in deleting the newly inserted node in your list.
Should I use free() at all?
Yes, since you are using malloc(). The memory you allocated dynamically should be de-allocated by you, otherwise memory leaks shall happen.
then where should I be using free() then?
In the place of your code that you do not need your list anymore. For example, at the end of your main().
Unrelated, but by looking at your insert(), I can see that head is a global variable, which should be avoided, when able. Passing it as a parameter to your list functions, and making this variable non global is a better approach. If you want, take a look in this list's code, which is fully commented and was the one I used to learn.
Do I cast the result of malloc? No!

malloc is doing strange things with memory addresses

I am doing a bucket sort, sorting pointers to nodes into a linked list with a dummy header. The user inputs the values for the nodes, and then they are immediately dropped into their appropriate bucket. My problem arises when I am attempting to allocate the memory for the second node (not including the dummy header) for the linked list.
This is the code used to drop the nodes into the bucket, var being the value that is being sorted, and current being the newly created node to be sorted:
void bucketSort(int var, nodeptr current)
if(!bucket[var])
{
buckets[var] = (nodeptr) malloc(sizeof(nodeptr));
buckets[var]->next = current;
bucketrear[var] = current;
}
else
{
bucketrear[var]->next = current;
bucketrear[var] = current;
}
}
This is a simplified version (less values) of the code used to create the new node:
void addNode(int value)
{
nodeptr newNode;
newNode= (nodeptr) malloc(sizeof(nodeptr));
newNode->value = value;
newNode->next = NULL;
bucketDrop(value, newNode);
}
With Trace Statements, I discovered that before the Malloc of the second Node (with same value as the first), the Address of the bucket[value]->next was a normal address, but afterwards the address was 17. This value of 17 came up in every single test that I did.
Any help or ideas would be great. Thankyou in advance.
I think this is one of solution.
buckets[var] = (nodeptr) malloc(sizeof(*buckets[var]));
newNode= (nodeptr) malloc(sizeof(*newNode));
You're mixing up the struct for your node and the pointer pointing to it and thus overwriting the memory location.
Since you're casting the malloc result to a nodeptr type it means that this is a pointer (since malloc() returns a pointer) which also means your're allocating memory the size of a pointer.
So given that you named your struct nodestruct, to allocate enough memory you'd write
newNode = (nodeptr) malloc(sizeof(struct nodestruct));
The following should resolve your issue:
newNode= (nodeptr) malloc(sizeof(*nodeptr));
The reason is nodeptr looks to be a pointer to struct, and hence you should allocate memory for the struct instead of a pointer.
From, next time please paste your struct definitions also.

Adding nodes to a global linked-list

I am attempting to construct my first linked list, and having read a basic introduction, have done the following. Firstly, declare a linked list node as:
struct errorNode {
uint8 error;
struct errorNode* next;
};
Secondly, define the first node globally as:
struct errorNode errorList = {0, NULL};
This has been done to allow each of the libraries that make up my current project to insert errors into a common list. The function to do this is:
void errorListWrite(uint8 error) {
struct errorNode* newNode = malloc(sizeof(struct errorNode));
newNode->error = error;
newNode->next = &errorList;
errorList = *newNode;
}
Whilst this compiles without error, it does not function as expected. I thnk the problem is with the last two statements of the list write function, but I am unsure. A hint as to what I am doing wrong would be most appreciated.
The problem is that you create a circular list.
newNode->next = &errorList;
So newNode links to the global node.
errorList = *newNode;
This is equivalent to errorList.error = newNode->error; errorList.next = newNode->next;.
So now errorList links to the global node. Oops.
What you could do instead, is insert the new node after the global node in the list:
newNode->next = errorList.next;
errorList.next = newNode;
This is assuming that you want a global node at all. If you don't, then you could start with struct errorNode *errorList = 0;, and add a new node like this:
newNode->next = errorList;
errorList = newNode;
When you come to use the list, your list-traversal may look a little different. With a global pointer-to-node you'll start with a pointer to the first node, that you must check for null before using. With a global node you'd start with a node that definitely exists, but whose next pointer might be null.
Well, the problem is with the last line: you are just overwriting the data in in the old error node!
What you probably need is to have the head (pointer to the first node) globally accessible, not the first node itself. This way you don't need a fake entry in your list.
(Be warned that your code is not thread-safe.)
Code:
errorNode* pGlobalErrorList = NULL;
// in errorListWrite
newNode->next = pGlobalErrorList;
pGlobalErrorList = newNode;
Your head (errorList) should be a pointer and should be initialized to NULL unless you have a need for the initial entry of a node with a value of 0:
struct errorNode* errorList = NULL;
Then your function needs to reassign errorList properly.
void errorListWrite(uint8 error) {
struct errorNode* newNode = malloc(sizeof(struct errorNode));
newNode->error = error;
newNode->next = errorList;
errorList = newNode;
}
This is all assuming your new node will be the new head of the list, and not the new tail.
errorList should be a pointer to first node (not the first node)
also you need to know what is the last node this will be modified
the head of list will not be modified, it will be used only when you want to travel from the beginning of list.

Memory Allocation Freeing

I'm currently writing a linked list and trying to free up memory allocations when I delete a node. However, after hours of trying to do this, I can't seem to get a clean valgrind output.
void * pop(struct List *list)
{
if(list->head == 0){
return 0;
}
struct Node * tempNode = list->head->next;
free(list->head);
list->head = tempNode;
...
}
I'm allocating the space by saying:
addNode(struct List *list, void *element){
struct Node *node;
node = (struct Node *)malloc(sizeof(node));
....
}
Basically in the pop function I want to take out the head of the list and make the head's next node the new head. I want to deallocate the memory that was given to head.
Thanks for any help
Woah, your malloc isn't correct. You have:
(struct Node *)malloc(sizeof(node));
What you need is:
(struct Node *)malloc(sizeof(struct Node));
In your original code, you are only allocating enough for a pointer. But you are trying allocate a Node object.
node = malloc(sizeof(*node));
Allocate space for the thing pointed to by node.
Don't cast the return value of malloc. Doing so can mask the failure to #include <stdlib.h>.
It seems correct. Or are there some leaks in the other places? Or do you free the element itself as the parameter passed in ?

Resources