【问题标题】:Array of pointers to structs in a pointer to a struct指向结构的指针中的指向结构的指针数组
【发布时间】:2018-05-18 08:34:49
【问题描述】:

下面的代码尝试初始化一个节点,并在这样做时动态初始化一个指向子节点的指针数组。但是,当我尝试访问孩子时,我得到了Segmentation fault: 11。我意识到我不应该得到任何有意义的值(即它只会在内存中成为垃圾),但我不知道为什么会出现分段错误。

#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>

#define INIT_SIZE 10

typedef struct node_t node_t;

struct node_t {
  char *word;
  node_t **children;
  int arr_len;
};

void set_array_vals(node_t *root);

int main(int argc, char const *argv[]) {
    char *word = "hello";

    node_t *root = malloc(sizeof(node_t));
    assert(root);

    root->children = malloc(sizeof(node_t *) * INIT_SIZE);
    assert(root->children);
    root->arr_len = INIT_SIZE;

    root->word = malloc((sizeof(char)) * (strlen(word) + 1));
    assert(root->word);
    strcpy(root->word, word);

    set_array_vals(root);
    printf("Arr len: %d\n", root->arr_len);

    return 0;
}

void set_array_vals(node_t *root) {
    int i;
    for (i=1; i<root->arr_len; i++) {
        node_t *this_node = root->children[i];
        printf("%d: %d\n", i, this_node->arr_len);
    }
}

【问题讨论】:

  • 您已经为包含指向子节点的指针的数组分配了内存,但实际上并没有为子节点分配内存。
  • 计算你拥有的malloc(sizeof(node_t))的数量和你期望的节点数量。
  • 啊,你是对的。所以从这里开始,我应该为每个数组位置(指向节点的指针)分配一个节点来为孩子分配内存?
  • 没错,你可以在set_array_vals本身的循环中做。
  • 请不要更改关于答案的问题。这使答案看起来错误。能否请您回滚到修订版 1?

标签: c memory-management tree


【解决方案1】:

set_array_vals 中,您从“数组”root-&gt;children 获得指针,但该数组未初始化,并且指针将是不确定的 并且看似随机。取消引用这些指针会导致undefined behavior

另外,您似乎忘记了数组索引从 开始。而且一旦你使root-&gt;children数组中的所有指针都有效,你必须记得初始化它们指向的结构,否则this_node-&gt;arr_len的值将是不确定的。

【讨论】:

  • 实际上,set_array_vals 没有做任何事情,因为它使用了一个局部变量。是啊。它使用未初始化的取消引用内存。
【解决方案2】:

正如其他人所指出的,首先children 属于node_t ** 类型,并且您只为root-&gt;children 分配了内存,而不是为root-&gt;children[row]。为root-&gt;children[row] 动态分配内存并分配一些值。它可能看起来像

 root->arr_len = INIT_SIZE;
 for(int row = 0; row < root->arr_len ;row++) {
         root->children[row] = malloc(sizeof(node_t));/* allocate memory for each children */
         root->children[row]->arr_len = row + 99;/* ?? assign some values into member of struct so that you can print in
                                                                            set_array_vals & verify  */
            }

set_array_vals() 中从i=0 开始打印,如上所述,您将内存从root-&gt;children[0] 分配到root-&gt;children[9],并且访问超出大小可能会导致未定义的行为。

void set_array_vals(node_t *root) {
        for (int i = 0; i < root->arr_len; i++) { /* start printing from i=0 , not i=1 */
                #if 0
                node_t *this_node = root->children[i]; /* no need of any temporary pointer */
                printf("%d: %d\n", i, this_node->arr_len);
                #endif
                printf("%d: %d\n", i, root->children[i]->arr_len);
        }
}

【讨论】:

    猜你喜欢
    • 2017-06-03
    • 1970-01-01
    • 2012-12-07
    • 2016-06-20
    • 1970-01-01
    相关资源
    最近更新 更多