So here's my code for destroying a linked list.
void destroy(node *h){
if (h->next!=NULL){
destroy(h->next);
}
free(h);
h=NULL;
}
The problem is that printing still outputs a bunch of numbers:
11, 2, 15, 3, 9, //Before Destroy
28495936, 28495968, 28496064, 28496096, 0, //After Destroy
Unfortunately I cannot alter the void destroy(node *h) parameters due to assignment reasons.
I've tried using a while loop method but I still get the same result. I've also tried shifting to the left and deleting from the end but then I wouldn't be able to delete the last node.
thanks in advance.
--edit---
as requested, here is the print function
void print(node* N){
printf("%d, ", N->value);
if (N->next)
print_set(N->next);
if (N == NULL)
printf("Empty Set");
}
You must set h->next = NULL. Also, after the call to destroy, make sure you don't use the pointer anymore because it is freed. So, always after destroy(n), make sure that you have n = NULL.
A better way is probably to change the signature to void destroy(node **h), so the code becomes:
void destroy(node **h){
if ((*h)->next!=NULL){
destroy(&h->next);
}
free(*h);
*h=NULL;
}
Then you ensures that you are not using the pointer afterwards.
In your print function, you must add this check at the beginning:
if(N == NULL) return;
If the solution provided by Albert is not possible due to some rules, the only possibility you as the author of the source in question have is to remember the list's nodes had been deallocated and therefore contain invalid references to memory and that the code you write because of the latter may not dereference such pointers, that is they may not be passed to the printing functions as this would provoke undefined behaviour by accessing un/deallocated memory.
If writing such potential insecure code, it is in your responsibilty as the author to use it carefully and document it very well for your fellow programmers maintaining the code after you left the project.
The problem here is that h=null in your function does not do anything. You're modifying a local parameter so it won't have any effect outside the function.
Thus, the only thing you do is freeing the memory, but you keep the address the same. Your list still exists, pointing to random memory location (well not random : the same as before, but the values at this memory locations are random)
When you print your list after that (which is strange because you're supposed to have destroyed it... Why would you want to print it again ?), you print random values in memory.
This is a problem because your program could also crash (you're accessing memory which is not allocated).
The solution, unfortunately, requires to change the signature of your function :
void destroy(node **h){
if ((*h)->next!=NULL){
destroy((*h)->next);
}
free(*h);
*h=NULL;
}
If you can't, you have to set the pointer to NULL after destroying it, like this:
void destroy(node *h){
if (h->next!=NULL){
destroy(h->next);
h->next=NULL;
}
free(h);
}
and in the calling function:
destroy(myList);
myList=NULL;
The problem is probably in code you haven't posted!
I assume you keep a 'head' pointer to your list, and your code looks like this.
Node * myList;
.. do stuff..
destroy(myList);
print(myList);
The problem is that you don't set myList = NULL following the destroy.
destroy(myList);
myList = NULL;
print(myList);
Your h=NULL in destroy() doesn't do anything because it's modifying a local parameter.
I don't know what your structure looks like, but I'm guessing something like this:
struct {
int something;
int* value;
list* next;
}
The problem is that even though h is the NULL pointer, h->value and h->next are not. They are pointers in NULL+1 and NULL+2, which may point to random places in memory.
Try this code if u are working on singly linked list
void destroy(node *h){
node *n;
node *p; \\ variable to store previous term
n=h;
while(n->next!=NULL){
p = n;
}
p->next=NULL;
free(n);
}
Related
FINAL EDIT
My function that frees the memory works properly, and as milevyo has suggested, the problem lies in node creation, which I had fixed. I now have a separate problem where the program segfaults when run normally, but it cannot be reproduced in gdb or valgrind. However, that is a separate question altogether.
I have since found out that this segfault happened because I did not check for the EOF character properly. As per Cliff B's answer in this question, the check for EOF happens only after the last character in the file. As a result, in my function that loads the dictionary file, I had assigned the last character of the file to some i (which in this case was -1 according to a printf call), and tried to create and access a child node if index -1. This caused a segmentation fault, and also caused problems with my unload function, which would not unload the very last node I created.
As to why the segmentation fault does not appear when I run the program in gdb or valgrind, I have no idea.
EDIT 3
While stepping through my load function where the node creation happens, I notice an unexpected behaviour. I believe the problem lies somewhere in these lines of code, which are embedded within a for loop. The casting to (node*) is just to be safe, though it does not affect the running of the code to my knowledge.
// if node doesnt exist, calloc one, go to node
if (current_node->children[i] == NULL)
{
current_node->children[i] = (node*) calloc(1, sizeof(node));
nodes++;
}
current_node = current_node->children[i];
While stepping through the load function, I see that my current_node->children[i] seem to be calloc'ed properly (all children set to NULL), but the moment I step into current_node->children[i] and examine its children (see image below), I see that the addresses get screwed up. Specifically, the i'th child in the children node gets set to 0x0 for some reason. While 0x0 is supposed to be equal to NULL (correct me if I'm wrong), my free_all function seems to want to go into the 0x0 pointer, which of course results in a segfault. Can anyone shed light on how this might happen?
Values of children[i]
EDIT 2: I'm using calloc to create my nodes
root = calloc(1, sizeof(node));
For my child nodes, they are created within a for loop where I iterate over characters of the dictionary file I'm reading in.
if (current_node->children[i] == NULL)
{
current_node->children[i] = calloc(1, sizeof(node));
nodes++;
}
c in this case represents the character of the word being read in. I get i using the following:
if (c == '\'')
i = 26;
else if (isalpha(c))
i = c - 97;
EDIT: I'm thinking that something in my node creation is faulty, as milevyo suggested. This is because if I print out the addresses, it goes from 0x603250 to 0x603340 to 0x603430 to 0x603520, then finally to (nil), before it segfaults. I have verified that the root node gets passed in correctly by printing out its value in gdb. I'll try to figure it out.
ORIGINAL QUESTION
I'm running into a segfault when trying to free a recursive struct, but cannot figure out why, and would like some help.
My struct is defined as follows:
typedef struct node
{
bool is_word;
struct node* children[27];
}
node;
This is meant to implement a trie structure in which to load a dictionary into, for purposes of a spellcheck. After the spellcheck is done, I need to free the memory that I've allocated to the trie.
This is my current function which should free the trie when passed the root node, but it segfaults when doing so, though not immediately:
void free_all(node* curs)
{
int i;
// recursive case (go to end of trie)
for (i = 0; i < 27; i++)
{
if (curs->children[i] != NULL)
{
free_all(curs->children[i]);
}
}
// base case
free(curs);
}
Where could I have gone wrong? If more information is needed, please let me know.
i think, root node is faulty ( maybe it is null). if not, look elsewhere. in node creation for example.
void free_all(node* curs)
{
int i;
if(!curs) return; // safe guard including root node.
// recursive case (go to end of trie)
for (i = 0; i < 27; i++)
free_all(curs->children[i]);
// base case
free(curs);
}
The free_all function is ok. You have to check you set to NULL all children not allocated. This includes nodes that are not leaves, but don't have all the 27 children.
If that is ok, or fixing it doesn't fix the segfault, you have to debug.
I got a binary tree playing the game to guess the user's guess.
All worked fine until I tried to free the binary tree.
I used the valgrind to check, they give me these:
==8205== Invalid read of size 8
==8205== at 0x400F0A: treePrint (in /home/mbax4nc2/COMP26120/ex6/pangolin)
==8205== by 0x400A14: main (in /home/mbax4nc2/COMP26120/ex6/pangolin)
==8205== Address 0x4c334a8 is 200 bytes inside a block of size 216 free'd
==8205== at 0x4A06430: free (vg_replace_malloc.c:446)
==8205== by 0x400DEE: freeTree (in /home/mbax4nc2/COMP26120/ex6/pangolin)
==8205== by 0x400A08: main (in /home/mbax4nc2/COMP26120/ex6/pangolin)
typedef struct node{
char name[100];
char question[100];
struct node *yes;
struct node *no;
}node;
void freeTree(node *root)
{ //Tree's root note is passed as argument
if (root == NULL)
{
return;
}
if (root->no != NULL)
{
freeTree(root->no);
root->no = NULL;
}
if (root->yes != NULL)
{
freeTree(root->yes);
root->yes = NULL;
}
free(root);
return;
}
I didn't paste all my program in here, because it was really a long version. What's wrong with my free() function? How could I debug it? I didn't know how to use the valgrind record to fix my program.
To debug dynamic memory management: Count all calls to malloc(), calloc(), realloc(NULL, ...) and strdup(), sum them up and then count all calls to free(), excluding calls to free(NULL). The former and the later count shall match, if the don't you found a bug.
Just as a note: If the two counts mentioned above match, this does not mean memory management is done correctly.
just simple as this:
void freeTree(node *root)
{
if (!root )
return;
freeTree(root->no);
freeTree(root->yes);
free(root);
return;
}
It looks to me like the error may have been caused not by the free function but somewhere else in the code. Your free function looks ok to me even though it could be simpler like in milevyo's answer. If I had to guess I would say that you are not correctly initializing the yes and no pointers to null. By default they will point to some invalid memory. You need to set them to null any time you add a new node. It would help if you posted the rest of the code.
Actually I just looked at the comments and you said you called print after calling free. This should work so long as you set the root node to null after calling freeTree (assuming your print function correctly handles empty null trees). I notice that this function will not change the root node even though it frees it. The free function does not change the value of a pointer and that pointer will still point to the same location. I always set pointers to null after freeing them just to be safe.
This is my code to add node at beginning.
void screate(ll *node)
{
ll *newNode=(ll *)malloc(sizeof(ll));
printf("Enter number :\t");
scanf("%d",&newNode->data);
if(newNode->data != NULL)
{
newNode->next=node;
node= newNode;
screate(node);
}
else
{
free(newNode);
newNode=NULL;
}
}
Even i found same code here, I unable to figure out, why I getting wrong output.
This is the current node
56->78->77->NULL
But, when i'm trying to add new node at the beginning, then still I'm getting same output i.e. 56->78->77->NULL. Need Help !!
UPDATE
void show(ll *node){
while(node->next != NULL)
{
printf("%d->",node->data);
node=node->next;
}
printf("NULL");
}
You're assigning to node which is just a parameter to the function. Since it's passed by value, this won't update the version held by the calling function.
You need to pass a pointer to it instead (i.e. ll **node) and change your code to assign to *node, and also changer the caller to add a & before the argument to take its address.
void screate(ll **node)
{
ll *newNode=malloc(sizeof(ll));
printf("Enter number :\t");
scanf("%d",&newNode->data);
if(newNode->data != NULL)
{
newNode->next=*node;
*node= newNode;
screate(node);
}
else
{
free(newNode);
}
}
If you pass a pointer to something to a function, it can change the something but not the pointer itself. The natural conclusion is therefore to make the something itself the pointer - i.e. a pointer to a pointer.
In principle you can take this pointer chaining as deep as you like, but in practice you won't generally need anything more than "pointer to pointer to thing".
Couple of other points. Try to avoid variable names like l and ll as lowercase L's can easily be confused with the digit 1 (and an uppercase I) in many fonts. Also, your use of a recursive call into screate() again would be potentially more efficient as a while loop instead. Some compilers will spot that it's tail-recursive and optimise to a loop anyway, but I never like to rely on that sort of thing when it's just as clear to use a loop in the first place.
newNode->next=node;
node = newNode;
The problem is that node = newNode only changes the local copy of node which means the caller doesn't see the change. For the caller it's as if you never called the function, node still points to wherever it pointed before.
You may want to pass a ll **node and change *node or something else.
You should change the signature with parameter as a pointer to linked list pointer
void screate(ll **node);
And your corresponding pointer changes in your function must be like this
newNode->next=*node;
*node= newNode;
screate(&node);
I would suggest changing your screate function so that it returns a struct ll *. The return value would correspond to your new head node.
if(newNode->data != NULL) is not a sensible way to detect input failures from scanf. In fact, that line of code isn't sensible, period. NULL is identified as a member of the set of null pointers. newNode->data is an int, not a pointer. Comparing it to 0 would make more sense. [Here][1] is a standardised scanf reference. Read it carefully and answer the following questions, and you will know how to distinguish between success and failure of scanf:
int x, y;
int z = scanf("%d%d", &x, &y);
int c = getchar();
If I send "abcd{enter}" through stdin, what will z be?
If I send "abcd{enter}" through stdin, what will c be?
If I send an EOF signal through stdin, what will scanf return?
Which value would z be, if it successfully read and put values into the two variables x and y?
I have a function that adds one item to a list that I created. If it's the first time and the list points to NULL, it allocates the list and completes it, returning the address. If it's not the first time, it adds another item and again returns the first item (by now I could disregard this return). The list and the function WORKS fine, here is the prototype:
typedef struct structTAppConsoleList {
char *text;
void (*cbFunction)(int);
int number; // This is the item number
struct structTAppConsoleList *previous;
struct structTAppConsoleList *next;
} TList;
TList *AppConsoleListAddItem(TList *p_list, const char *p_string, void (*p_funcPtr)(int));
So, somewhere in my code I have to create a lot of them and I'm trying to make it as the code below shows. Thing is, I can't make it work... I want to create something to group the lists I want to create and then use it in the function. The code below is an idea of what I'm trying to do. Consider only the part where I try to allocate the 3 lists, the rest is not important for this example.
TList *list1;
TList *list2;
TList *list3;
int main(void)
{
int i,j;
TList **groupMyLists;
TList *temp;
groupMyLists=malloc(sizeof(TList)*3);
*groupMyLists =(TList*)&list1;
*(groupMyLists+1)=(TList*)&list2;
*(groupMyLists+2)=(TList*)&list3;
for(j=0;j<3;j++) {
temp=NULL;
for(i=0;i<10;i++) {
temp=AppConsoleListAddItem(temp,"some text",someFunc);
}
**groupMyLists=temp; // my make won't let me do this
groupMyLists++;
}
}
I'm pretty sure that this would do it, but I can't compile it.
In my head, (*groupMyLists) would be the same as (&list1), (&list2), (&list3), the same way that (**groupMyLists) would be the same as (list1), (list2) and (list3). So why I can't do (**groupMyLists=temp)? Anyone?
I hope I made myself clear!! I's not easy to explain this madness I'm trying to do...
Change this line, you are using the wrong indirection.
*groupMyLists=temp;
In addition to the above two answers about the incorrect indirection of **groupMyLists you probably also want to assign the list1,list2,list3 pointers correct pointer values instead of writing garbage values into the allocated memory in groupMyLists i.e.
TList * groupMyList = malloc(sizeof(TList)*3);
list1 = &groupMyList[0];
list2 = &groupMyList[1];
list3 = &groupMyList[2];
but, this does not really match the rest of your code as it seems that AppConsoleAddListItem allocates the temp list so in that case your malloc would be incorrect as it should allocate the space for the pointers instead of space for the lists as in:
TList ** groupMyList = (TList **)malloc(sizeof(TList *)*3);
TList * temp;
if (!groupMyList) {
/* Print allocation error warning or handle in some proper fashion */
exit(1);
}
for(j=0;j<3;j++) {
temp=NULL;
for(i=0;i<10;i++) {
temp=AppConsoleListAddItem(temp,"some text",someFunc);
}
groupMyLists[j]=temp; // Here you now assign the pointer in temp to the memory for // pointers that you allocated above
}
list1 = groupMyList[0]; // Here we need to assign the list1,2,3 after the AppConsole calls
list2 = groupMyList[1]; // as these calls will changes the pointer addresses written into
list3 = groupMyList[2]; // groupMyList
Although I can not be sure exactly what you are trying to do there are several inconsistencies of pointers and indirections in your original code and the above two examples can hopefully be of some guidance
This would do the job:
**groupMyLists = *temp;
of copying one struct referenced by temp to another struct referenced by *groupMyLists.
But only if *groupMyLists would reference any valid memory, which is does not do - at least not from the source you posted.
My goal is to run a API call repeatedly and check for memory leaks.
The API takes in integer input and returns a pointer to the first structure in a linked list of structures as output. Each structure may have struct variables of other types.
In the following code i have tried to represent my problem.
The problem is in callApi() function. I need to dispose of the memory occupied by the structure 'output' that the API() returns. Even if i use free(output) here, it will cause a memory leak because since it points to a linked list of nested structures. (source of info : http://en.wikibooks.org/wiki/C_Programming/Memory_management)
Question:
When leaving exiting callApi() call, will the 'output' nested structure expire when control goes out of the function back to main()? Will it free the entire memory occupied? Please suggest a solution to way to solve this memory leak problem.
Can this problem be overcome with C++?
typedef struct{
int dev_size;
char *dev_name;
dev_stat *next_dev;
mem_stat *mem_info;
} dev_stat
typedef struct{
int mem_capacity;
char *mem_name;
} mem_stat
int main()
{
int input;
int return_val;
int callApi(int);
while(1)
{
return_val=callApi(input);
print return_val;
}
}
int callApi(int ip)
{
//Update: Memory allocation is unnecessary as it is done inside the API() call itself
//dev_stat *output=(dev_stat *)calloc(2,sizeof(dev_stat));
int ret_val;
ret_val=API(ip,&output);
free(output);
output=NULL;
return ret_val;
}
The simple answer is, no, the memory will not "expire" when you exit a function.
The API should provide a way to "free" the returned value, if it is a complex structure. If it doesn't, then traversing the structure yourself and freeing it is probably the only way out.
The first question who is the owner of the structures you are going to free.
It might be that the API returns a pointer to its internal structure, which you must not deallocate (because, for example, it may be shared).
It might be as well that your code is responsible for deallocating the structure itself, but not the other structures that your structure points to. This way you need to just free the returned structure and forget about it.
It might be however that your responsibility is to free the whole object tree starting at the returned structure. In that case it's to be expected that the API has some function which properly deallocates the structure with its descendants for you. If not (which is most likely not the case), you have to free all the resources referenced by your structure, recursively.
You should look up at the APi documentation to find out which if the three cases is your case.
Update:
Explicitly for your case (the whole structure should be deallocated manually), I would use something like that:
void free_mem_stat(struct mem_stat* p)
{
if (!p) return;
free(p->mem_name);
free(p);
}
void free_dev_stat(struct dev_stat* p)
{
// first, clean up the leaves
for(struct dev_stat* curr = p; curr; curr = curr->next_dev)
{
free(curr->dev_name);
free_mem_stat(curr->mem_info);
}
// than, clean up the linked list
for(struct dev_stat* curr = p; curr; /**/)
{
struct dev_stat* next = curr->next_dev;
free(curr);
curr = next;
}
}
int callApi(int ip)
{
int ret_val;
struct dev_stat* output;
ret_val = API(ip, &output);
free_dev_stat(output);
return ret_val;
}
Note that the function like free_dev_stat ought to be provided by the API itself, if the API developers really intend to let the users deallocate their structures.