2011-09-29 60 views
2

为什么我在这里得到一个访问冲突读取位置0xC0000005,如果在我在linux中编码时,相同的代码就像一个魅力一样?C++访问违规?

if(nodo->izq!=NULL) //nodo is a class or struct and "sig" is a pointer of the same kind 
    VaciarAux(nodo->izq); 

有没有办法在没有未处理的异常的情况下完成这个任务? 断言会做的伎俩?

这里是功能

void Arbol<T>::VaciarAux(Nodo<T> * &nodo) 
{ 
    if(nodo->izq!=NULL) 
     VaciarAux(nodo->izq); 
    if(nodo->der!=NULL) 
     VaciarAux(nodo->der); 
    if(nodo->izq == NULL && nodo->der ==NULL) 
    { 
     actual = nodo; 
     nodo=NULL; 
     delete actual; 
     contador--; 
    } 
+0

'assert'只是作为您的程序的健全性检查。任何使用'assert'完成的检查都不应该存在于生产代码中。你可能在某处读取了未初始化的内存,因此你的NULL检查通过了,但是随后你进入了随机存储区。但是,您应该发布更多代码来帮助评估您的问题。 – Pablo

+0

没有足够的信息在您的问题需要足够的答复。访问违规可能是出于任何原因。 –

+0

你是什么意思“断言会做诡计”?问问题时始终要非常具体。 –

回答

4

最有可能的,因为nodo本身是无效的指针。 ->取消引用会导致问题。

您需要检查可能影响该值的事情(导致损坏的缓冲区溢出,由于某种原因设置为NULL)。

需要注意的是:

if (nodo->izq != NULL) 

检查,如果nodo变量为NULL,而是如果有什么nodoizq成员为NULL。

如果你只是想要做什么,如果nodo本身是NULL,你可以把在开始:

if (nodo == NULL) return; 

,但我仍然认为你会好得多回溯到问题的根源而不是仅仅修复一个症状。


我认为问题出在您处理树的方式。你是切实做好:

def delTree (node): 
    if node.left != NULL: 
     delTree (node.left) 
    if node.right != NULL: 
     delTree (node.right) 
    if node.left == NULL and node.right == NULL: 
     delete node and whatever else you have to do 

与主要的问题是,delTree (node.left)意味着,如果树是空的,你会得到你看到确切的问题,因为你试图做的第一件事就是废弃的空根节点。

更通常的做法是先复发孩子无条件地(用NULL保护器),然后处理节点本身,是这样的:

def delTree (node): 
    if node == NULL: 
     return 
    delTree (node.left) 
    delTree (node.right) 
    delete node and whatever else you have to do 

这将正确处理空树,仍然正确删除所有儿童在父母面前。它只是看起来更优雅,这是首先使用递归的原因之一:-)

我将它作为一个练习,让读者把它变成C++。

+0

所以用一个空根初始化一棵树是不好的做法? – HoNgOuRu

+0

不,这实际上是相当标准的 - 它是一棵空的树。我想我现在看到了你的情况(尽管语言有困难) - 我会更新答案。 – paxdiablo

+0

如果(nodo-> izq!= NULL) 我需要在此行中返回false的真,那就是我决定沿着树枝向左或向右的位置。 – HoNgOuRu

0

您可能想要了解如何创建Nodo类型(即查看其默认构造函数...应该有一个,因为它是包含指针的类/结构)。例如,如果您未初始化Nodo类型的成员,以便每当创建一个Nodo对象时,这两个指针成员初始为NULL,则它们可以具有任何不确定的值,以便Arbol<T>::VaciarAux内的NULL值的测试将失败。例如,一个新的Nodo最终会被初始化为某个随机值的指针,但包含在Nodo的指针成员中的那些随机存储器值不是在内存中可访问的有效位置。然后,当您测试指针是否为NULL时,测试结果为false,并且您尝试在下一次递归调用Arbol<T>::VaciarAux时解除引用它们,导致访问冲突。

+0

endeed,我有一个NULL值初始化它们在默认的构造函数 – HoNgOuRu

+0

模板 类Nodo { 市民: Nodo(常量DNodo datoPasado, Nodo * izqPasado = NULL,NULL Nodo * derPasado = NULL) ();();();()()()()()()()()()() – HoNgOuRu

+0

树中有多少个节点?这种访问违规似乎是随机发生的,还是在一定数量的节点之后发生? – Jason

1

由于pax认为这可能是一个糟糕的指针。在Linux中,可能没有严格的虚拟内存规则,因为在其他地方运行代码时(也取决于编译器)。所以在Linux的情况下,它可能正在工作,但它可能实际上正在做你不期望的事情。

+0

Linux有严格的内存规则。然而,它可能是在Linux上,他有一个有效的随机指针 – Dani

+0

是的,因为malloc分配基于页面的指针可以在页面边界有效。严格来说,我的意思是在Windows中某些由malloc调用的区域会标记为PROTECTED,因此在释放(有些情况下)之前或者在它们被调入之前不能实际使用它们 –