c++访问冲突

C++ Access violation?

本文关键字:访问冲突 c++      更新时间:2023-10-16

如果我在linux中编码时相同的代码像魅力一样工作,为什么我在这里获得访问违反读取位置0xC0000005 ?

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

有没有办法在没有未处理异常的情况下完成这个任务?Assert能达到目的吗?

下面是函数

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--;
    }

很可能是因为nodo本身是一个无效的指针。然后->解引用将导致一个问题。

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

注意:

if (nodo->izq != NULL)

不检查nodo变量是否为NULL,而是检查nodo所指向的izq成员是否为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根节点。

更常见的方法是首先无条件地重复子节点(使用NULL保护器),然后处理节点本身,如:
def delTree (node):
    if node == NULL:
        return
    delTree (node.left)
    delTree (node.right)
    delete node and whatever else you have to do

这将正确地处理空树,并且仍然正确地删除父树之前的所有子树。而且看起来更优雅,这是首先使用递归的原因之一:-)

我将把它作为一个练习留给读者把它变成c++。

正如pax所说,这可能是一个不好的指针。在Linux中,在其他地方运行代码时可能没有严格的虚拟内存规则(也取决于编译器)。所以在Linux的情况下,它可能会工作,但它实际上可能会做一些你意想不到的事情。

你可能想看看你是如何创建一个Nodo类型(即,看看它的默认构造函数…它应该有一个,因为它是一个包含指针的类/结构)。例如,如果您没有初始化Nodo类型的成员,以便在创建Nodo对象时两个指针成员初始化为NULL,那么它们可能具有任何不确定的值,从而导致Arbol<T>::VaciarAuxNULL值的测试失败。例如,一个新的Nodo将以初始化为一些随机值的指针结束,但是Nodo的指针成员中包含的随机内存值不是内存中可访问的有效位置。然后,当您测试指针是否为NULL时,测试结果为false,并且您试图在下一次递归调用Arbol<T>::VaciarAux时解引用它们,从而导致访问冲突。