C++ 访问冲突?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7592367/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 17:11:10  来源:igfitidea点击:

C++ Access violation?

c++access-violation

提问by HoNgOuRu

Why am I getting an access violation reading location 0xC0000005 here if the same code works like a charm when I coding in linux?

如果我在 linux 中编码时相同的代码像魅力一样工作,为什么我会在这里收到访问冲突读取位置 0xC0000005?

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

Is there any way of getting this done without that unhandled exception? assert will do the trick?

如果没有未处理的异常,有没有办法完成这项工作?assert 会起作用吗?

here is the function

这是功能

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

回答by paxdiablo

Most likely because nodoitself is an invalid pointer. The ->dereferencing would then cause a problem.

很可能是因为nodo它本身是一个无效的指针。在->随后取消引用会产生问题。

You need to check the things that could possibly affect that value (buffer overflows causing corruption, having set to NULL for some reason).

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

Note that:

注意:

if (nodo->izq != NULL)

does notcheck if the nodovariable is NULL but rather if the izqmember of what nodopoints to is NULL.

没有检查nodo变量为NULL,而是如果izq什么成员nodo指向为NULL。

If you simply want to do nothing if nodoitself is NULL, you could put at the start:

如果你只想在nodo它本身为 NULL 的情况下什么都不做,你可以把它放在开头:

if (nodo == NULL) return;

but I still think you'd be much better off tracking back to the source of the problem rather than just fixing one symptom.

但我仍然认为你最好追溯到问题的根源,而不是仅仅解决一个症状。



I think the problem is with the way you are processing the tree. You are effectively doing:

我认为问题在于您处理树的方式。你正在有效地做:

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

The main problem with that is that delTree (node.left)means that you'll get the exact problem you're seeing if the tree is empty since the first thing you try to do is dereference the NULL root node.

这样做的主要问题是,这delTree (node.left)意味着如果树为空,您将得到确切的问题,因为您尝试做的第一件事是取消引用 NULL 根节点。

The more usual approach is to first recur the children unconditionally (with a NULL protector) then process the node itself, something like:

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

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

This will correctly handle an empty tree and still correctly delete all children before the parent. And it just looksmore elegant, which is one of the reasons to use recursion in the first place :-)

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

I'll leave it as an exercise for the reader to turn that back into C++.

我将把它作为练习让读者把它转回 C++。

回答by Jesus Ramos

As pax says it's probably a bad pointer. In Linux there may not be strict virtual memory rules as when running the code somewhere else (also depends on the compiler). So in the Linux case it might be working but it might actually be doing something you don't expect.

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

回答by Jason

You may want to look into how you are creating a Nodotype (i.e., look at its default constructor ... it should have one since it's a class/struct that contains pointers). For instance, if you are not initializing the members of a Nodotype so that the two pointer members are initially NULLwhenever a Nodoobject is created, then they could have any indeterminant value such that the tests for NULLvalues inside of Arbol<T>::VaciarAuxwill fail. For instance, a new Nodowould end up with pointers initialized to some random value, but those random memory values contained in the pointer-members of Nodoare not valid locations accessible in memory. Then when you test whether the pointers are NULL, the test comes out false, and you attempt to dereference them in the next recursive call to Arbol<T>::VaciarAux, causing an access violation.

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