I have a linked-list like chain of structs that point to eachother. Normally it wouldn't be so difficult, but I'm running into problems freeing memory that has already been freed, because different structs can point to the same struct down below. Now, I am not referring to freeing a node itself, but rather an element within the node (a matrix). The issue is not that I am freeing an object that I am referencing later, it is that I am freeing a member of an object multiple times. It looks like this:
d
/ \
c b
/ \
a b
where if I just recurse through the graph, I'll end up freeing a member of b
twice. Thus, I need a way to update b
's state with some boolean value done
after I free it's member once so that when I come across it a second time I can avoid freeing something that has already been freed.
The structure obj
is acting as a sort of node within this chain. The goal is for prev
to be an array of previous nodes (order doesn't matter). If a node a
has a previous node prev
b
, where b
also has prev
set to say, c
, the purpose is to be able to recurse through until you find all nodes that have no prev
set (effectively a leaf node). The issue is that, the way this is currently implemented, updating the states of any nodes that are stored in prev
does not actually update the value of the initial node
- instead, it just updates the value of the node within obj->prev
.
I have some test code for the scenario that I am dealing with:
#include <stdio.h>
#include <stdlib.h>
typedef struct obj obj;
struct obj {
char name;
int done;
obj* prev;
};
void recurse(obj *o) {
printf("(before) node %c: %i\n", o->name, o->done);
o->done = 0;
printf("(after) node %c: %i\n", o->name, o->done);
if (o->prev) {
// *this* should be generalized to handle for n elems in
// prev, and can be handled by just adding a num_prev value
// to obj
recurse(o->prev);
recurse(o->prev+1);
}
}
int main() {
obj node1 = {'a', 1, NULL};
obj node2 = {'b', 1, NULL};
obj node3 = {'c', 0, NULL};
node3.prev = (obj *)malloc(2 * sizeof(obj));
*node3.prev = node1;
*(node3.prev+1) = node2;
obj node4 = {'d', 0, NULL};
node4.prev = (obj *)malloc(2 * sizeof(obj));
*node4.prev = node3;
*(node4.prev+1) = node2;
recurse(&node4);
printf("(final) node %c: %i\n", node1.name, node1.done);
printf("(final) node %c: %i\n", node2.name, node2.done);
free(node3.prev);
free(node4.prev);
}
where the output ends up being:
(before) node d: 0
(after) node d: 0
(before) node c: 0
(after) node c: 0
(before) node a: 1
(after) node a: 0
(before) node b: 1
(after) node b: 0
(before) node b: 1
(after) node b: 0
(final) node a: 1
(final) node b: 1
As you can see through the results, two things are happening. First, b
(node2) is getting recursed twice, but the second time the value is still set to 1
(even though it was just set to 0
). The second thing is that after the whole program execution, a
(node1) and b
(node2) are both not updated.
I think it's something like: I'm only updating the local (copied) pointer of a->val
and not the actual pointer of a
(I think that sounds right).