2013-10-24 72 views
0

我有一个函数func()需要一个双指针。如果它指向零,则函数退出(首先检查)。现在没有第二次检查,我得到访问冲突尝试访问mybar的成员(当我第二次运行该功能时)。这是为什么?如果mybar == NULL不应该在第一次检查时退出?使用双指针访问冲突

func(Foo **bar) 
{ 
    //First check 
    if(bar== NULL) 
    return; 

    Foo *mybar = *bar; 

    //Second check 
    if(mybar == NULL) 
     return; 

    if(mybar->member != NULL) //Access violation here if I dont have the 'second check' 
    { 
     //do stuff 
    }  
    delete mybar; 

    *bar = NULL; 

} 

那我怎么称呼它:

Foo *bar = NULL; 
initialize(&bar); 
func(&bar); 
func(&bar); //Second time I call it, I get the access violation 
+1

显示如何调用函数 –

+0

@claptrap谢谢,我添加了该调用。事实上,当我第二次打电话时它会打击。我想证明它,所以我实际上可以再次调用它,它只是在没有访问冲突的情况下返回。 – tzippy

+0

向你展示* initialize()*函数。 – KBart

回答

2

您的bar变量永远不会是NULL,因为它不是动态变量。你可能弄错了这样的定义:

Foo *bar = NULL; 

这里bar是一种非动态分配的变量,所以&bar总是(在此范围内)的有效地址。它只有NULL地址。

比方说,你在你的initialiase()功能动态分配更多的内存来bar,那么你的第一个电话会看:

func(address_of_bar) 

而这个函数里面,*bar指向动态分配的内存(一个有效的,非NULL地址)。然后,您通过delete mybar释放该内存,然后转换为delete *bar

当你调用func()第二次,呼叫本身仍然是相同的 - func(address_of_bar),正如我前面提到的,&bar总是非NULL这里。但是在这个函数中,*bar == NULL,因为你第一次调用func()时已经删除了动态分配的内存。这就是为什么你的第一张支票通过,但第二张支票失败。

编辑:为避免这种混淆,我建议使用不同的变量名和函数参数,特别是当它们是不同类型时(Foo *bar vs Foo **bar)。

+0

谢谢!我添加了第一个检查'if(bar == NULL || * bar == NULL)' – tzippy

0

那可能是因为如果你的指针指向空或不是你不检查。

首先检查if(bar== NULL)说,你的指针不为NULL,它仍然可以指向一个NULL值(这只是一个地址毕竟) 第二次检查if(mybar == NULL)不完全一样的。指针不为空(指定了某个地址),但它仍然可以指向NULL值。你没有检查,你试图访问对象的字段,可能是NULL。

0

mybar不必是NULL才能导致访问冲突。它可能指向进程地址之外,受保护的内存或其他地方无效。

您很可能忘记了在代码中的其他地方初始化这些指针。