C比较后,初始化变量的值自行改变
我正在用C实现一个简单的树结构。程序显示了一些奇怪的行为,我能够将它缩小到一个地方,在这个地方,存储在内存位置并使用指针访问的值会意外地发生变化。它是可复制的,但仅在递归函数运行几次(取决于输入的确定性)后发生。它位于while语句头的某个地方。我在“while”之前检查过,所有指针都指向预期的、定义良好的等内容的内存单元。最让我头疼的是,即使我将值的副本分配给另一个变量,该变量也会发生变化。我不知道这是怎么可能的,尽管我怀疑我明显遗漏了什么。下面是相关的代码片段C比较后,初始化变量的值自行改变,c,C,我正在用C实现一个简单的树结构。程序显示了一些奇怪的行为,我能够将它缩小到一个地方,在这个地方,存储在内存位置并使用指针访问的值会意外地发生变化。它是可复制的,但仅在递归函数运行几次(取决于输入的确定性)后发生。它位于while语句头的某个地方。我在“while”之前检查过,所有指针都指向预期的、定义良好的等内容的内存单元。最让我头疼的是,即使我将值的副本分配给另一个变量,该变量也会发生变化。我不知道这是怎么可能的,尽管我怀疑我明显遗漏了什么。下面是相关的代码片段 typedef struct
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_节点(子节点)设置额外断点后代码>我注意到执行指令的顺序有问题。一次,程序直接从自由节点(子节点)运行在进行条件检查时,绕过至环路内部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;
}
问题是当get\u first(children)==get\u last(children)
while循环应该有它的最后一次迭代。但是,delete_subtree_aux
无法更新children->next
指向的位置。当位于该地址的节点的子节点
空闲时,while循环不会停止,而是尝试再进行一次迭代(因为子节点->下一个
指向一些节点
——类似内存中的垃圾,与子节点
不同)。然而,这一次,它试图访问免费的子项
,这当然会导致错误
正如@Holsety在评论中指出的那样,在之前和内部之间“i”、“j”、“children”和“n”的神秘变化是查看堆栈上不同级别递归函数的结果。在调试器下运行程序,并设置与变量j
相关的观察点。当j
的值发生变化时,调试器将停止程序。至少您会看到程序的哪一行负责更改,我打赌这不是assert
。当然不是assert。如前所述,更改j的行是while语句的头(因此while(!(children->next->root==children->root)){
)也可能不是那一行。因此,运行调试器。因为您的delete_子树\u aux
是递归的,我认为您在调试器中查看的j
与您预期的不同。请检查您的j
holds-4和holds-3是否具有相同的地址。我认为您查看的delete_子树\u aux
函数,所以实际上没有问题。在递归时,您的函数有多个调用堆栈。最终结果是否错误?