【问题标题】:Initializing struct member of type struct pointer to null将结构指针类型的结构成员初始化为空
【发布时间】:2018-11-25 18:31:57
【问题描述】:

我在将空值分配给指向结构成员的指针(这也是指向结构的指针)时遇到问题。下面的代码正确地将headNode->right 变量设置为null,而不是headNode->left 变量。

typedef struct node {
    char *key;
    int frequency;
    struct node *left;
    struct node *right;
    struct node *parent;
} node;


void addKey(char key[]) {
    extern node *headNode;
    node *newNode;

    if (headNode != NULL) {
        printf("Head node is initialized\n");
        if (headNode->left != NULL) printf("    Left is not null\n");
        if (headNode->right != NULL) printf("    Right is not null\n");
    }


    newNode = malloc(sizeof(node*));
    newNode->key = malloc(sizeof(char) * (strlen(key) + 1));
    newNode->left = malloc(sizeof(node*));
    newNode->right = malloc(sizeof(node*));
    newNode->parent = malloc(sizeof(node*));


    newNode->left = newNode->right = NULL;
    newNode->frequency = 1;
    newNode->right = NULL;
    strcpy(newNode->key, key);

    // If this is the first node, assign it as the root
    if (headNode == NULL) {
        newNode->parent = NULL;
        headNode = newNode;
        return;
    }
}

但是,如果我在 return 语句之前添加以下两行,它可以正常工作。

if (headNode->left == NULL) printf("L is null\n");
else printf("L is NOT null\n");

我不明白 if 语句如何产生影响。在我的代码中,没有其他地方可以分配或更改此变量的值。

【问题讨论】:

  • 如果我在最后一个 return 语句之前添加以下两行 – 只有一个 return 语句位于 if 中,它建立了 headNode == NULL !?
  • 我尽量避免使用这种语法:newNode->left = newNode->right = NULL,因为评估顺序会有所不同,而且会让人困惑。还有为什么要在两行之后设置newNode->right = NULL

标签: c


【解决方案1】:

所有malloc(sizeof(node*)) 都应该是malloc(sizeof(node))。您只是为指针分配了足够的空间,而不是整个结构。这会导致以下所有通过这些指针间接进行的代码的未定义行为。

【讨论】:

    【解决方案2】:

    退后一步。这里有很多严重的错误。

    你声明了一个指向node的指针:

    node *newNode;

    到目前为止,一切都很好。但是,当您尝试为这个新节点分配内存时,您只分配了足够的内存来存储指针,而不是节点本身:

    newNode = malloc(sizeof(node*));

    您已经有指针的存储空间:newNode

    将此行更改为:

    newNode = malloc(sizeof(node));

    过了一会儿,你又给malloc打了三个不必要的电话:

    newNode->left = malloc(sizeof(node*));
    newNode->right = malloc(sizeof(node*));
    newNode->parent = malloc(sizeof(node*));
    

    如果您在上一次调用中请求了足够的内存(即sizeof(node)),则无需为这些内部字段分配更多内存。你已经对他们有记忆了;它已经存在于newNode指向的地址。

    更糟糕的是,你会在下一行继续泄漏内存:

    newNode->left = newNode->right = NULL;

    在这里你丢弃了你不必要分配的内存地址。

    我认为您需要进一步阅读内存管理,然后我们才能为您解决此问题。

    【讨论】:

    • 感谢您的详细回复。我应该意识到我需要为结构分配足够的内存,而不是为 newNode 分配指针。我记得之前想通了,我只是完全空白。至于三个不必要的 malloc 调用,那是我试图根据其他 SO 帖子弄清楚的。你的解释是有道理的,为什么这是不必要的。关于内存泄漏;我将如何处理?在创建它们最终指向的节点之前,我需要将这些值设置为 NULL。再次感谢您的回复。
    • @Jake 没问题。对不起,如果我的回答听起来很刺耳。看起来你对指针还不满意——这很酷,它们是 C 中更棘手的概念之一。但它们在坏人手中也非常危险,因此在尝试构建树和列表等之前,确保这些东西是第二天性是值得的。
    • 对不起,我不小心提前发布了这个,并在上面添加了一个编辑。不用担心,我绝对知道我需要更好地了解它们。
    • 关于内存泄漏,如果你一开始只是简单地使用malloc(sizeof(node)),你可以像你一样将newNode->leftnewNode->right设置为NULL。这些值将在newNode 指向的内存块中简单地为零。稍后,当你想调用free(newNode)时,你需要检查newNode->leftnewNode->right是否非NULL,并首先处理它们(如果它们不是NULL,它们将指向不同的内存块需要分别为freed。这些东西应该包含在deleteNode函数中。
    • 知道了。再次感谢您,这真的很有帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-22
    • 1970-01-01
    • 1970-01-01
    • 2012-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多