我在C中实现了一个简单的树结构。程序显示了一些奇怪的行为,我能够将它缩小到一个地方,其中值存储在内存位置并通过使用指针访问意外地更改。它是可复制的,但只能在递归函数的几次运行(具体取决于输入)之后发生。它位于'while'语句标题的某处。我已经在'while'之前检查了所有指针指向具有预期的,明确定义的内容的存储器单元。最让我感到烦恼的是,即使我将值的副本分配给另一个变量,变量也会变化。我不知道怎么可能,虽然我怀疑有一些显而易见的东西我不知道。以下是相关的代码片段。
typedef struct _Node {
int root;
struct _Node *children;
struct _Node *next;
struct _Node *previous;
} Node;
int delete_subtree_aux(Node *n) {
Node *children = get_children(n);
int i = children->root;
int j = i;
// At this point i and j both equal e.g. -4
while (!(children->next->root == children->root)) {
i = children->root;
// At this point i equals -3
assert(i == j);
// And j equals -3 too!
delete_subtree_aux(get_first(children));
}
free_node(children);
}
非常感谢所有帮助!
编辑:
在free_node(children);
设置了额外的断点后,我注意到执行了指令的顺序已经关闭。同时,程序直接从free_node(children);
循环到循环内部,绕过while
条件检查。 'n','i','j'和'children'一起变化并对应不同的函数输入。设置数据断点显示不同的'j'位于两个不同的内存地址。
在我看来,由于某种原因,这个函数的一些实例以某种方式在并列中执行,但这不是我的意图。我的后续问题是,在这种情况下释放内存会导致错误吗?如果是,我该怎么做才能解决它?
编辑2: 上面代码中调用的其他函数的来源:
int free_node(Node *n) {
free(n);
}
Node *get_children(Node *n) {
return n->children;
}
Node *get_first(Node *list) {
return list->next;
}
答案 0 :(得分:0)
问题是当get_first(children) == get_last(children)
while循环应该有它的最后一次迭代。但是,delete_subtree_aux
无法更新children->next
指向的位置。当此地址的节点children
空闲时,while循环而不是停止,尝试再做一次迭代(因为children->next
指向某些Node
- 就像垃圾一样在内存中与children
不同。但是,这一次,它会尝试访问免费的children
,这当然会导致错误。
神奇地改变了儿童,儿童'和' n'在while
之前和内部之间是查看堆栈上不同级别的递归函数的结果,正如@Holsety在评论中指出的那样。