I am implementing a simple tree structure in C. The program showed some strange behaviour, and I was able to narrow it down to a place, where value stored in a memory location and accessed by using pointers unexpectedly changes. It is replicable, but only happens after a few runs (depending deterministically on the input) of a recursive function. It is in somewhere in the header of 'while' statement. I have checked that just before 'while' all pointers point to memory cells that have expected, well-defined etc. content. What bugs me most, is that even if I assign copy of the value to another variable that variable changes too. I have no idea how it is possible, though I suspect there's something obvious I'm missing. Below are relevant code fragments.
typedef struct _Node {
int root;
struct _Node *children;
struct _Node *next;
struct _Node *previous;
} Node;
int delete_subtree_aux(Node *n) {
Node *children = get_children(n);
int i = children->root;
int j = i;
// At this point i and j both equal e.g. -4
while (!(children->next->root == children->root)) {
i = children->root;
// At this point i equals -3
assert(i == j);
// And j equals -3 too!
delete_subtree_aux(get_first(children));
}
free_node(children);
}
All help is greatly appreciated!
Edit:
After setting additional breakpoint at free_node(children); I have noticed that something is off with the order of instructions executed. At one time program goes straight from free_node(children); to the inside of the loop bypassing while condition checking. 'n', 'i', 'j' and 'children' change together and correspond to different function inputs. Setting data breakpoints revealed that different 'j's are at two different memory addresses.
It seems to me, like for some reason that a few instances of this function are somehow executed in paralell, but that's not my intention. My follow-up question is, can freeing memory in such conditions cause errors? If yes, what should I do to fix it?
Edit 2:
Source for other functions called in the code above:
int free_node(Node *n) {
free(n);
}
Node *get_children(Node *n) {
return n->children;
}
Node *get_first(Node *list) {
return list->next;
}
The problem was that when get_first(children) == get_last(children) the while loop should have its last iteration. However, delete_subtree_aux fails to update where children->next points to. When children of the node at this address are free'd, the while loop instead of stopping, tries to do one more iteration (since children->next points to some Node-like garbage in memory that is different to children). This time however, it tries to access free'd children, and that of course causes error.
The mysterious changing of 'i', 'j', 'children', and 'n' between before while and inside were a result of viewing different levels of recursive function on the stack, as pointed out by #Holsety in the comments.
Related
I have a program with the following structs:
typedef struct slide
{
int number;
int maxX;
int y;
int r, g, b;
struct line *first;
} slide;
typedef struct line {
char content[256]; // number subject to change
int r, g, b;
struct line *prev;
struct line *next;
} line;
Creating instances of these structs is done with the following code:
slide* createSlideArray(int s) {
slide* slides = malloc(sizeof(struct slide)*s);
return slides;
}
line *nextLine(line *prev) {
line *n = malloc(sizeof(line));
n->prev = prev;
prev->next = n;
return n;
}
And finally here is the code to free the structs after the program loop finishes, and before a new file is opened:
void freeLines(line *l) {
line *next;
while(l) {
next = l->next;
free(l);
l = next;
}
}
in main:
int i;
for (i=0;i<slideCount;i++) {
freeLines(slides[i].first); // works through next till NULL
}
free(slides);
As you can see, an instance of the slide struct holds a "first" line struct, the line struct is a doubly linked list. The line's content is read to the screen (using ncurses)
While in the program loop the user can type a command :open filename to open a new file, this is where my issue lies.
This slides and lines should be freed. When the loop starts again it'll open a new file, create the slides and lines, and use them as the content. The content, however, is partially filled with garbage text. I'm pretty sure this issue is in the lines struct and how it is being free. I'm not seeing that I'm doing wrong however.
Edit: I should make it clear that on the first iteration of the program the text is perfect, it is only when I try to parse a new file that the garbage text appears, and it is very homogeneous (appears at the front of each line, same characters)
I'm on Ubuntu if that makes a difference.
Here is a link to the project: DSS
There are some clear issues that I can spot from reading the code in your post. I can't definitively say if these are responsible for your problem as the code in your post is not a compilable example and I didn't go delving into your linked project.
Your nextLine function:
You have neglected to set n->next.
You have also neglected setting the prev pointer of the following node if there is one. ( prev->next->prev if prev->next != NULL ).
You current design precludes you from using this function to setup the first node in the list. It also does not show how you intend to create that node.
This function does not allow you to add a node to the begining of the list.
Your createSlideArray function:
This function does not initialize the slides it creates. These slide instances must be initialized. It seems sensible to do it here, but you might have a good reason to do it elsewhere. In either case, initializing the slideObject.first member is critical. Without this you will not be able to tell if the slide has a list of lines or not and your freeLines function will fail as it will be passed garbage as its parameter.
Note:
A different way of implementing doubly linked lists is using a "head node" which is always present and links to the first and last node in the list. This simplifies some issues, but changes others. You can research this if you are interested.
I was able to fix the issue by simply making proper calls to memset. for lines I was able to do the following:
memset(l, 0, sizeof(*l));
It is important that you are getting the size of the value at the l pointer, and not the size of the pointer itself, otherwise you won't properly free the memory. This was the issue that I was facing.
I have a struct Node and Box given by
typedef struct Node{
Particle p;
Box box;
struct Node *son[4];
}Node
and
typedef struct Box{
double low[3];
double up[3];
}Box
I have two functions insert() and sonumb() where I want to use these structures.
void insert(Particle *p, Node *t){
Box sonbox;
int b=sonumb(&t->box, &sonbox, p);
t->son[b]->box = sonbox; // <--- Produces Segmentation fault (core dumped)
}
int sonumb(Box *box, Box *sonbox, Particle *p){
int b=0;
for(int d=0;d<3;d++){
sonbox->up[d] = 0.5*box->up[d];
sonbox->low[d] = 0.5*box->low[d];
}
b=1; // b=[0,3] just for this example
}
sonum() returns an integer value b. sonbox represents after the call of sonumb() a smaller box inside of t->box. I return the right values for sonbox after the call. So sonbox is not empty. But if I want to copy those values like t->son[b]->box = sonbox I get an segmentatioin fault. What did I miss?
You have nearly certainly missed the allocation of son elements. In order for the expression t->son[b]->box to produce a valid target of an assignment, t->son[b] needs to be assigned a pointer to a valid Node structure. The pointer needs to point to some Node that you have previously allocated.
If child nodes are shared among nodes, this should be a malloc-ed node. This adds quite a bit of complexity, because deleting shared nodes is non-trivial. Two common approaches to working with shared nodes are to (1) allocate all nodes at once in a large array, and use them one-by-one as they become needed, and (2) add reference count to the struct, increment it when taking a pointer, and decrement it when the reference is no longer needed. The second approach is extremely difficult to implement; see if you can avoid it before committing to it.
On the other hand, if child nodes are owned exclusively by their parent, you have a very simple solution: allocate Node with malloc before the assignment of son[b] elements, and free them when you are done with the node:
Box sonbox;
int b=sonumb(&t->box, &sonbox, p);
t->son[b] = calloc(1, sizeof(Node)); // Allocate the node
t->son[b]->box = sonbox;
Use of calloc ensures that the memory of the Node is cleared prior to making other assignments. If this is not necessary, because you assign all members in the rest of your function, replace the call with malloc:
t->son[b] = malloc(sizeof(Node));
adding to #dasblinkenlight's comment.
Box sonbox; ---> This variable is on stack
int b=sonumb(&t->box, &sonbox, p); --> content of t->box is COPIED to sonbox, not by reference but by value.
t->son[b]->box = sonbox; // --> Assigning stack variable is incorrect, because it will vanish once you exit function. OR as #dasblinkenlight suggested pass the value but not the pointer.
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'm studying linked lists from this lesson.
The writer (and all other coders on every single tutorial) goes through creating node type pointer variables, then allocates memory to them using typecasting and malloc. It seems kinda unnecessary to me (Offourse I know I'm missing something), why can't we implement the same using this?
struct node
{
int data;
struct node *next;
};
int main()
{
struct node head;
struct node second;
struct node third;
head.data = 1;
head.next = &second;
second.data = 2;
second.next = &third;
third.data = 3;
third.next = NULL;
getchar();
return 0;
}
I've created nodes and the next pointers points towards the addresses of the next nodes...
Let's say you create a variable of type node called my_node:
struct node my_node;
You can access its members as my_node.data and my_node.next because it is not a pointer. Your code, however, will only be able to create 3 nodes. Let's say you have a loop that asks the user for a number and stores that number in the linked list, stopping only when the user types in 0. You don't know when the user will type in 0, so you have to have a way of creating variables while the program is running. "Creating a variable" at runtime is called dynamic memory allocation and is done by calling malloc, which always returns a pointer. Don't forget to free the dynamically allocated data after it is no longer needed, to do so call the free function with the pointer returned by malloc. The tutorial you mentioned is just explaining the fundamental concepts of linked lists, in an actual program you're not going to limit yourself to a fixed number of nodes but will instead make the linked list resizable depending on information you only have at runtime (unless a fixed-sized linked list is all you need).
Edit:
"Creating a variable at runtime" was just a highly simplified way of explaining the need for pointers. When you call malloc, it allocates memory on the heap and gives you an address, which you must store in a pointer.
int var = 5;
int * ptr = &var;
In this case, ptr is a variable (it was declared in all its glory) that holds the address of another variable, and so it is called a pointer. Now consider an excerpt from the tutorial you mentioned:
struct node* head = NULL;
head = (struct node*)malloc(sizeof(struct node));
In this case, the variable head will point to data allocated on the heap at runtime.
If you keep allocating nodes on the heap and assigning the returned address to the next member of the last node in the linked list, you will be able to iterate over the linked list simply by writing pointer_to_node = pointer_to_node->next. Example:
struct node * my_node = head; // my_node points to the first node in the linked list
while (true)
{
printf("%d\n", my_node->data); // print the data of the node we're iterating over
my_node = my_node->next; // advance the my_node pointer to the next node
if (my_node->next == NULL) // let's assume that the 'next' member of the last node is always set to NULL
{
printf("%d\n", my_node->data);
break;
}
}
You can, of course, insert an element into any position of the linked list, not just at the end as I mentioned above. Note though that the only node you ever have a name for is head, all the others are accessed through pointers because you can't possibly name all nodes your program will ever have a hold of.
When you declare 'struct node xyz;' in a function, it exists only so long as that function exists. If you add it to a linked list and then exit the function, that object no longer exists, but the linked list still has a reference to it. On the other hand, if you allocate it from the heap and add it to the linked list, it will still exist until it is removed from the linked list and deleted.
This mechanism allows an arbitrary number of nodes to be created at various times throughout your program and inserted into the linked list. The method you show above only allows a fixed number of specific items to be placed in the list for a short duration. You can do that, but it serves little purpose, since you could have just accessed the items directly outside the list.
Of course you can do like that. but how far ? how many nodes are you going to create ? We use linkedlists when we don't know how many entries we need when we create the list. So how can you create nodes ? How much ?
That's why we use malloc() (or new nodes).
But what if you had a file containing an unknown number of entries, and you needed to iterate over them, adding each one to the linked list? Think about how you might do that without malloc.
You would have a loop, and in each iteration you need to create a completely new "instance" of a node, different to all the other nodes. If you just had a bunch of locals, each loop iteration they would still be the same locals.
Your code and approach is correct as long as you know the number of nodes that you need in advance. In many cases, though, the number of nodes depends on user input and is not known in advance.
You definitely have to decide between C and C++, because typecasting and malloc belong in C only. Your C++ linked list code won't be doing typecasting nor using malloc precisely because it's not C code, but C++ code.
Say you are writing an application such as a text editor. The writer of the application has no idea how big a file a user in the future may want to edit.
Making the editor always use a large amount of memory is not helpful in multi-tasking environments, especially one with a large number of users.
With malloc() an editing application can take additional amounts of memory from the heap as required, with different processes using different amounts of memory, without large amounts of memory being wasted.
You can, and you can exploit this technique to create cute code like this, to use the stack as a malloc in a way:
The code below should be safe enough assuming there are no tail optimizations enabled.
#include <stdio.h>
typedef struct node_t {
struct node_t *next;
int cur;
int n;
} node_t;
void factorial(node_t *state, void (*then)(node_t *))
{
node_t tmp;
if (state->n <= 1) {
then(state);
} else {
tmp.next = state;
tmp.cur = state->n * state->cur;
tmp.n = state->n - 1;
printf("down: %x %d %d.\n", tmp);
factorial(&tmp, then);
printf("up: %x %d %d.\n", tmp);
}
}
void andThen(node_t *result)
{
while (result != (node_t *)0) {
printf("printing: %x %d %d.\n", *result);
result = result->next;
}
}
int main(int argc, char **argv)
{
node_t initial_state;
node_t *result_state;
initial_state.next = (node_t *)0;
initial_state.n = 6; // factorial of
initial_state.cur = 1; // identity for factorial
factorial(&initial_state, andThen);
}
result:
$ ./fact
down: 28ff34 6 5.
down: 28ff04 30 4.
down: 28fed4 120 3.
down: 28fea4 360 2.
down: 28fe74 720 1.
printing: 28fe74 720 1.
printing: 28fea4 360 2.
printing: 28fed4 120 3.
printing: 28ff04 30 4.
printing: 28ff34 6 5.
printing: 0 1 6.
up: 28fe74 720 1.
up: 28fea4 360 2.
up: 28fed4 120 3.
up: 28ff04 30 4.
up: 28ff34 6 5.
factorial works differently than usual because we can't return the result to caller because the caller will invalidate it with any single stack operation. a single function call will destroy the result, so instead, we must pass it to another function that will have its own frame on top of the current result, which will not invalidate the arbitrary number of stack frames it's sitting on top of that hold our nodes.
I imagine there are many ways for this to break other than tail call optimizations, but it's really elegant when it doesn't, because the links are guaranteed to be fairly cache local, since they are fairly close to each other, and there is no malloc/free needed for arbitrary sized consecutive allocations, since everything is cleaned as soon as returns happen.
Lets think you are making an Application like CHROME web browser, then you wanna create link between tabs created by user at run time which can only possible if you use Dynamic Memory Allocation.
That's why we use new, malloc() etc to apply dynamic memory allocation.
☺:).
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);
}