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!
Related
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.
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.
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.
Here's my function to delete a linked list:
void deleteList( NODE* head )
{
NODE* temp1;
NODE* tempNext;
temp1 = head;
tempNext = NULL;
while( temp1 != NULL )
{
tempNext = temp1->next;
free(temp1);
temp1 = tempNext;
}
}
So temp1 first points where the head pointer is pointing. If it isn't NULL, tempNext will be set to point to the next element of the list. Then the first element (temp1) is free'd, and temp1 is reassigned to point to where tempNext is pointing and process repeats.
Is this the right approach to deleting an entire list?
I ask this because when I print the list after using this function, it still prints the list. And IIRC freeing something doesn't delete it but only marks it as available so I'm not sure how to tell if this is correct or not.
Your code looks correct.
You're also correct that freeing a list's elements doesn't immediately change the memory they pointed to. It just returns the memory to the heap manager which may reallocate it in future.
If you want to make sure that client code doesn't continue to use a freed list, you could change deleteList to also NULL their NODE pointer:
void deleteList( NODE** head )
{
NODE* temp1 = *head;
/* your code as before */
*head = NULL;
}
It still print the list, because you probably don't set the head pointer to NULL after calling this function.
I ask this because when I print the list after using this function, it still prints the list.
There is a difference between freeing a pointer and invalidating a pointer. If you free your whole linked list and the head, it means that you no longer "own" the memory at the locations that head and all the next pointers point to. Thus you can't garintee what values will be there, or that the memory is valid.
However, the odds are pretty good that if you don't touch anything after freeing your linked list, you'll still be able to traverse it and print the values.
struct node{
int i;
struct node * next;
};
...
struct node * head = NULL;
head = malloc(sizeof(struct node));
head->i = 5;
head->next = NULL;
free(head);
printf("%d\n", head->i); // The odds are pretty good you'll see "5" here
You should always free your pointer, then directly set it to NULL because in the above code, while the comment is true. It's also dangerous to make any assumptions about how head will react/contain after you've called free().
This is a pretty old question, but maybe it'll help someone performing a search on the topic.
This is what I recently wrote to completely delete a singly-linked list. I see a lot of people who have heartburn over recursive algorithms involving large lists, for fear of running out of stack space. So here is an iterative version.
Just pass in the "head" pointer and the function takes care of the rest...
struct Node {
int i;
struct Node *next;
};
void DeleteList(struct Node *Head) {
struct Node *p_ptr;
p_ptr = Head;
while (p_ptr->next != NULL) {
p_ptr = p_ptr->next;
Head->next = p_ptr->next;
free(p_ptr);
p_ptr = Head;
}
free(p_ptr);
}
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 ?