I am having some trouble with pointers in C. Basically, we are tasked with programming an N-ary tree (family tree). Any single node can have any number of children (0, 1, 2, ...). I am stuck at the part of adding a single parent and a single child.
Theoretically, the parent should be the root and the child should be the child of the root. My add_child method is as follows (so far):
Node* add_child(Node** root, char* parent, char* child) {
Node* new_node = malloc(sizeof(Node));
//check for correct memory allocation of new_node here
new_node->name = child;
new_node->children = NULL;
new_node->child_count = 0;
if (*root == NULL) {
Node* parent = malloc(sizeof(Node));
parent->name = parent;
parent->children = malloc(sizeof(NodeList*));
NodeList* list = malloc(sizeof(NodeList));
list->data = new_node;
list->next = NULL;
parent->children = &list;
parent->child_count = 1;
*root = parent;
return;
}
}
Here are the structs:
typedef struct FieldNode {
char* name;
NodeList** children;
size_t child_count;
} Node;
typedef struct FieldNode_L {
Node* data;
NodeList* next;
} NodeList;
Now that we have that out of the way, I'll move onto the print_tree function, we should print the tree breadth-first (level-by-level). I have written the algorithm for this already, but it gets stuck pushing the children of a node onto the queue. To do this:
NodeList* current = *listPtr;
while (current->data != NULL) {
Node* to_add = current->data;
// set up queuenode and push it to the queue
current = current->next;
}
So theoretically, it should run once, push to the queue, then set current to the next, which is null, go back to check the while-loop condition, and fail and continue through the rest of the print_tree method. But this doesn't happen.
After debugging with gdb for what seems like 5 hours, I can tell you this:
- Before returning in add_child method, all of the memory locations are valid and point to the correct places. In gdb, with a breakpoint set, I can display all of the information through the root pointer (parent name, child count, and child name) by dereferencing.
- In the print_tree method, all of the information retains from the root that was set in the add_child method EXCEPT the children.
- The address that was set in the add_child method, and which I confirmed held the name I inputted had changed to a string filled with unicode characters ("\237\432\320....etc etc")
- My algorithm correctly prints the parent name, but then fails when adding the children and goes into an infinite loop as described above in the last code block.
So all in all, I have no idea why the contents have changed. I suspect that I am assigning values/addresses wrong in add_child (because the information is retained within the add_child function, but is lost in the other method) but I am confused because the root is holding some information but not all of it across functions.
I am very new at C and still trying to learn all this pointer stuff, for example double pointers... Any help with this problem would be appreciated!
VALGRIND EDIT: As requested, here is the valgrind output of the program, although I don't see how it is helpful. My code runs into an infinite loop, so my program has no chance to clean up the mess. In the last code block, where I show where how/where it infinite-loops, I commented out code that allocated space for a QueueNode. After running forever, it racks up a bunch of allocates but only 2 frees. That's why the output says it has that many.
GCC EDIT: As requested, I ran gcc with the flags -Wall -Wextra -pedantic and received the following output:
10:26: warning: unused parameter 'argv' [-Wunused-parameter]
154:27: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
89:1: warning: control reaches end of non-void function [-Wreturn-type]
I fixed the last two (comparison between signed and unsigned and the control reaching the end of a non-void function). The unused parameter I need later on, so I can't change that yet. It shouldn't effect anything anyway.
After fixing those problems, nothing has changed - the same error still occurs.