我有以下树节点结构,它包含指向其他树节点的指针:
struct node {
// ...
struct node* children[20];
}
我的想法是,我想检查node*
内部是否有children
并且更深入到树中。因此,当我分配node
时,我希望children
包含20 NULL
个值。
目前我不是在做什么
Conditional jump or move depends on uninitialised value(s)
(Valgrind)等错误?struct node** children
并分配固定大小会更好吗?编辑: Valgrind抱怨的一个地方的例子:
for(int i=0;i<20;i++)
if(node->children[i] != NULL)
do_something_with_the_node(node->children[i]);
答案 0 :(得分:1)
当您分配struct node
的新实例时,必须将包含的指针设置为NULL
,以将其标记为“不指向任何位置”。这将使Valgrind警告消失,因为指针将不再是未初始化的。
这样的事情:
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;
}
您无法在memset()
或 n->children
上轻松使用calloc()
,因为这些将为您提供“所有位为零”这与“指针NULL
”不同。
答案 1 :(得分:0)
你的结构定义是有效的(尽管如果符合你的要求,没有更多的上下文很难说明。)
Valgrind并没有抱怨你的结构定义,它可能会抱怨你如何实例化那种类型的变量。确保所有阵列成员都已初始化,投诉很可能会消失。
答案 2 :(得分:0)
问题是您在if
条件下使用未初始化的值。
当您实例化struct node
时,其成员struct node* children[20];
是一个20 struct node *
的数组,所有这些都未初始化。
与此无异:
char *x;
if (x == NULL) {
/* Stuff */
}
此时,x
可能确实具有任何价值。在您的示例中,数组的任何元素都可以具有任何值。
要解决此问题,您需要在使用它们之前初始化数组元素,例如:
for (int i = 0; i < 20; ++i) {
node->children[i] = NULL;
}
或更短:
memset(node->children, 0, 20);
如果您将会员更改为node **children
,那么情况可能会有所不同 - 您仍然需要初始化所有成员,包括数组& #39; s元素。你可以使用calloc
缩短它,这会将所有字节初始化为0
;再说一遍,你需要一些代码才能正确释放(并且记得这样做),所以我认为权衡不值得。