C++ C++;访问违规?

C++ C++;访问违规?,c++,access-violation,C++,Access Violation,当我在linux中编码时,如果相同的代码像一个符咒一样工作,为什么我在这里得到一个访问冲突读取位置0xC0000005 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(

当我在linux中编码时,如果相同的代码像一个符咒一样工作,为什么我在这里得到一个访问冲突读取位置0xC0000005

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--;
    }
void Arbol::VaciarAux(Nodo*&Nodo)
{
如果(nodo->izq!=NULL)
VaciarAux(nodo->izq);
如果(nodo->der!=NULL)
鱼子酱(nodo->der);
如果(nodo->izq==NULL&&nodo->der==NULL)
{
实际值=nodo;
nodo=NULL;
删除实际的;
康塔多--;
}

很可能是因为
nodo
本身是无效指针。
->
取消引用将导致问题

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

请注意:

if (nodo->izq != NULL)
不检查
nodo
变量是否为NULL,而是检查
nodo
指向的
izq
成员是否为NULL

如果如果
nodo
本身为空,您只想什么都不做,那么可以在开始处输入:

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)
意味着如果树是空的,那么您将看到确切的问题,因为您尝试做的第一件事就是取消对空根节点的引用

更常见的方法是首先无条件地重复出现子节点(使用空保护器),然后处理节点本身,如:

def delTree (node):
    if node == NULL:
        return
    delTree (node.left)
    delTree (node.right)
    delete node and whatever else you have to do
这将正确地处理一个空树,并且仍然正确地删除父树之前的所有子树。而且它看起来更优雅,这是首先使用递归的原因之一:-)


我将它留给读者作为一个练习,把它转回到C++。

你可能想看看你是如何创建<代码> Nodo < /C>类型(即,看看它的默认构造函数……它应该有一个,因为它是包含指针的类/结构)。。例如,如果您没有初始化
Nodo
类型的成员,因此每当创建
Nodo
对象时,两个指针成员最初都是
NULL
,那么它们可能具有任何不确定的值,因此
Arbol::VaciarAux
中的
NULL
值测试将失败。例如在这种情况下,新的
Nodo
将以初始化为某个随机值的指针结束,但
Nodo
指针成员中包含的随机内存值不是内存中可访问的有效位置。然后,当您测试指针是否为
NULL
时,测试结果为false,您将尝试取消引用它们在对
Arbol::VaciarAux
的下一个递归调用中,导致访问冲突。

正如pax所说,这可能是一个错误的指针。在Linux中,可能没有严格的虚拟内存规则,就像在其他地方运行代码一样(也取决于编译器)。因此,在Linux情况下,它可能会工作,但实际上可能会执行一些您不期望的操作。

assert
仅用于程序的健全性检查。使用
assert
执行的任何检查都不应出现在生产代码中。您可能在某处读取未初始化的内存,从而导致空检查通过,但随后您进入随机内存区域。但是,您应该发布更多代码来帮助评估您的问题。您的问题中没有足够的信息需要得到充分的答复。访问冲突可能是出于任何原因。您所说的“断言将起作用”是什么意思?提问时一定要非常具体。我在标题处将NULL定义为0。此函数是递归函数,它所做的是清理treeLinux具有严格的内存规则。然而,可能是在Linux上,他有一个有效的随机指针EAH,因为malloc是基于页面分配的,指针可以位于有效的页面边界内rict我的意思是,在Windows中,malloc调用的某些区域被标记为PROTECTED,因此在它们被释放后(在某些情况下)或在它们被mallocedso之前,您实际上无法使用它们。因此,用空根初始化树是一种不好的做法吗?不,这实际上是相当标准的-它是一个空树。我想我明白您现在的意思了(尽管有语言上的困难)-我会更新答案。如果(nodo->izq!=NULL)这是我决定跟随树枝的地方,我需要在这行中返回true或false,不管是左还是右。所以这是一个糟糕的做法,不知道他们为什么在university@paxdiablo问题:您提到了
delTree(node.left)
没有将
node.left
设置为NULL,但是由于他通过引用传递该指针,并且在删除节点时确实执行了
node=NULL;
操作,这不应该影响
node.left
的值吗?在上一个递归调用ended中,我正在使用默认构造函数模板的NULL值初始化它们类Nodo{public:Nodo(const-DNodo-datoPasado,Nodo*izqPasado=NULL,NULL-Nodo*derPasado=NULL):dato(datoPasado),izq(izqPasado),der(derPasado),equi(0){}Nodo();树中有多少个节点?这种访问冲突似乎是随机发生的,还是在一定数量的节点之后发生的?因为这是一种递归方法,我不应该问左或右子是否为NULL,这会导致访问冲突。我没有按照@paxdiablo的建议去做