Reputation: 24294
I have the following tree node struct that holds pointers to other tree nodes:
struct node {
// ...
struct node* children[20];
}
The idea is that I want to check whether there is node*
inside the children
and based and that go deeper into the tree. So when I allocate the node
I want to have children
with 20 NULL
values.
Currently I am not doin
Conditional jump or move depends on uninitialised value(s)
(Valgrind)?struct node** children
and allocate fixed size each time I allocate a new node?EDIT: Example of one place where Valgrind complains:
for(int i=0;i<20;i++)
if(node->children[i] != NULL)
do_something_with_the_node(node->children[i]);
Upvotes: 0
Views: 1248
Reputation: 399703
When you allocate a new instance of struct node
, you must set the contained pointers to NULL
to mark them as "not pointing anywhere". This will make the Valgrind warning go away, since the pointers will no longer be uninitialized.
Something like this:
struct node * node_new(void)
{
struct node *n = malloc(sizeof *n);
if(n != NULL)
{
for(size_t i = 0; i < sizeof n->children / sizeof *n->children; ++i)
n->children[i] = NULL;
}
return n;
}
You cannot portably use either memset()
on n->children
nor calloc()
, since those will give you "all bits zero" which is not the same as "pointer NULL
".
Upvotes: 1
Reputation: 1413
The problem is that you are using an unintialized value in an if
condition.
When you instantiate a struct node
, its member struct node* children[20];
is an array of 20 struct node *
, all of which are uninitialized.
It would be no different from this:
char *x;
if (x == NULL) {
/* Stuff */
}
At this point, x
may have literally any value. In your example, any element of an array may have any value.
To fix this, you need to initialize the elements of an array before using them, for example like this:
for (int i = 0; i < 20; ++i) {
node->children[i] = NULL;
}
Or shorter:
memset(node->children, 0, 20);
If you changed the member to, as you've suggested, node **children
, the situation wouldn't be much different - you'll still need to initialize all the members, including array's elements. You could make it shorter by using calloc
, which will initialize all bytes to 0
; then again, you'll need some code for correct deallocation (and remember to do it), so I think the tradeoff's not worth it.
Upvotes: 0
Reputation: 3335
Your struct definition is valid (although it's hard to tell without more context if it fits your requirements).
Valgrind doesn't complain about your struct definition, it probably complains about how you instantiate variables of that type. Ensure that all of the array members get initialized and the complaints will most likely go away.
Upvotes: 0