【问题标题】:C malloc stack vs heap issueC malloc堆栈与堆问题
【发布时间】:2015-12-18 21:00:13
【问题描述】:

我正在用 C 实现二叉搜索树的插入功能,但遇到了 malloc 的问题。

首先,我有一个树和节点结构

typedef struct Node {
    double value;

    struct Node *parent;
    struct Node *right_child;
    struct Node *left_child;
} Node;

typedef struct Tree {
    struct Node *root;
} Tree;

这是我的插入函数,用于向树中插入一个值。

void insert(Tree *t, double v) {

    Node *n = malloc(sizeof(Node));
    n->left_child = malloc(sizeof(Node));
    n->right_child = malloc(sizeof(Node));
    n->parent = malloc(sizeof(Node));
    n->value=v;

    Node *x = t->root, *y = NULL;

    //follow tree down until we reach a leaf of the tree
    while (x) {

        //save last non-NULL value. We will insert node n as a child to this leaf.
        y = x;

        if (n->value < x->value) {
            x = x->left_child;
        } else {
            x = x->right_child;
        }
    }

    //The parent of the node to insert is the leaf we reached
    n->parent = y;

    //If n is greater than y then it is its right child and vice-versa.
    if (n->value > y->value) {
        y->right_child = n;
    } else {
        y->left_child = n;
    }

}

还有我的主要方法

int main(void) {

    Node n1;

    n1.value = 4;
    n1.parent = NULL;
    n1.left_child = NULL;
    n1.right_child = NULL;

    Tree t;

    t.root = &n1;

    insert(&t,2.0);

    printf("In order traversal\n");
    inOrderTraversalNode(t.root);

    return EXIT_SUCCESS;
}

当我打印有序遍历代码时,我得到未定义的行为(例如:26815615859885194199148049996411692254958731641184786755447122887443528060147093953603748596333806855380063716372972101707507765623893139892867298012168192.000000)而不是正确的遍历。

我很确定问题出在insert 方法中的Node 创建。我认为问题在于堆栈中存在新节点,然后在 insert 函数退出时将其销毁 - 这就是导致遍历期间未定义行为的原因。但是,我认为malloc 将变量存储在堆上并使其全局可用。或者也许节点在堆上但指针在堆栈上?有人可以告诉我这里哪里出错了吗?

【问题讨论】:

  • 我看到main 创建了一个Node 并初始化了指向NULL 的指针,但是当insert 创建一个Node 时,它通过调用malloc 来初始化指针。但是malloc返回的Node本身并没有初始化。

标签: c binary-search-tree heap-memory stack-memory


【解决方案1】:

通过malloc分配的内存中的初始内容是未定义的。

首先,删除n-&gt;parent = malloc(sizeof(Node));,这会导致内存泄漏。

其次,改变

  n->left_child = malloc(sizeof(Node));
  n->right_child = malloc(sizeof(Node));

  n->left_child = NULL;
  n->right_child = NULL;

这样程序才能正确识别叶子。

【讨论】:

【解决方案2】:

尝试使用calloc 而不是malloc。问题是malloc 不会将值初始化为零,它 分配空间。 calloc 将您请求的空间归零。因此,当您到达一个无效但也不是NULL 的指针时,您偶尔会跳转到内存的随机部分。

malloc 和朋友们肯定会在堆上分配,你的想法是对的;它们返回的是一个指针,它指向内存中的空间,该空间至少是您请求的大小,绝对可以安全地读取和写入。但是,由于在您使用 malloc 时该值并未被清零,因此您无法保证存储在结构中的指针实际上指向有效位置。

编辑:另外,其他海报是正确的:您正在做的事情肯定存在内存泄漏。没听懂。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-18
    • 2014-06-23
    • 1970-01-01
    • 1970-01-01
    • 2010-10-03
    • 1970-01-01
    • 2018-06-24
    • 2013-07-06
    相关资源
    最近更新 更多