简体   繁体   English

结构内固定大小数组的内存分配

[英]Memory allocation of fixed size array inside a struct

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. 这个想法是,我要检查是否有node*里面children和基础和更深入的树。 So when I allocate the node I want to have children with 20 NULL values. 因此,当我分配node我想让children拥有20个NULL值。 Currently I am not doin 目前我不在

  1. How should I allocate this array in order to not get errors like Conditional jump or move depends on uninitialised value(s) (Valgrind)? 我应该如何分配此数组,以免出现诸如Conditional jump or move depends on uninitialised value(s)类的错误,该错误Conditional jump or move depends on uninitialised value(s) (Valgrind)?
  2. Would it be better to use struct node** children and allocate fixed size each time I allocate a new node? 每次分配新节点时,使用struct node** children并分配固定大小会更好吗?

EDIT: Example of one place where Valgrind complains: 编辑: Valgrind抱怨的一个地方的例子:

for(int i=0;i<20;i++)
  if(node->children[i] != NULL)
    do_something_with_the_node(node->children[i]);

When you allocate a new instance of struct node , you must set the contained pointers to NULL to mark them as "not pointing anywhere". 在分配struct node的新实例时,必须将包含的指针设置为NULL以将其标记为“无处指向”。 This will make the Valgrind warning go away, since the pointers will no longer be uninitialized. 这将使Valgrind警告消失,因为指针将不再被初始化。

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 ". 不能随便n->children上使用memset() 或在 calloc() ,因为这些将给您“所有位为零”,这与“指针NULL ”不同。

Your struct definition is valid (although it's hard to tell without more context if it fits your requirements). 您的struct定义是有效的(尽管没有更多上下文很难确定它是否满足您的要求)。

Valgrind doesn't complain about your struct definition, it probably complains about how you instantiate variables of that type. Valgrind不抱怨您的结构定义,它可能抱怨您如何实例化该类型的变量。 Ensure that all of the array members get initialized and the complaints will most likely go away. 确保所有数组成员都已初始化,并且投诉很可能会消失。

The problem is that you are using an unintialized value in an if condition. 问题是您在if条件中使用的是非初始化值。

When you instantiate a struct node , its member struct node* children[20]; 当实例化一个struct node ,它的成员struct node* children[20]; is an array of 20 struct node * , all of which are uninitialized. 是由20个struct node *的数组,所有这些struct node *均未初始化。

It would be no different from this: 与此没有什么不同:

char *x;

if (x == NULL) {
    /* Stuff */
}

At this point, x may have literally any value. 此时, x实际上可以具有任何值。 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. 如您所建议,如果将成员更改为node **children ,情况将不会有太大不同-您仍然需要初始化所有成员,包括数组的元素。 You could make it shorter by using calloc , which will initialize all bytes to 0 ; 您可以使用calloc使其更短一些,它将所有字节初始化为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. 再一次,您将需要一些代码来进行正确的重新分配(并记住要这样做),所以我认为这种权衡是不值得的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM