2016-09-28 40 views
0

我有一些代码,如下所示:在try/catch之外声明但在内部初始化的指针会导致未定义的行为?

class ClassA 
{ 
public: 
    ClassA(string p1, string p2); 
    void DoSomething(); 
}; 

int main() 
{ 
    ClassA *p = NULL; 

    try 
    { 
     // ... 
     // some external input that can throw 
     // ... 
     ClassA a{"some", "params"}; 
     p = &a; 
    } 
    catch(...) 
    { 
     // print error 
    } 

    if (p != NULL) { 
     p->DoSomething(); // <- causes segfault 
    } 
} 

道歉,如果这是个坏/愚蠢的代码(我是新的C++),但为什么叫a->DoSomething()导致段错误发生?显然,p被声明在try/catch块的作用域之外,并且p != NULL总是返回true,表明p不为空,因此已在try/catch块内正确初始化。

有人可以帮我理解吗?

+2

'a'在离开{}块后超出范围。所以现在'p'指向不再存在的东西 –

+0

p仍然指向一个范围之后的地址,但是指针中的值未定义 – Raindrop7

回答

2

指针被初始化为指向自动内部作用域中对象的实例。

当执行线程离开作用域时,对象被销毁,指针现在指向一个被销毁的对象。

而抛出的异常当然会留下声明对象的范围。

换句话说,指针指向的对象只存在于try块内,并且一旦自然执行离开try块,或者通过抛出的异常,对象就会被销毁。

异常被catch块捕获的事实是无关紧要的。

这是使用智能指针的另一个原因。如果对象在动态范围内被分配,并且所讨论的指针是unique_ptrshared_ptr,则通过catch块中的智能指针,该对象仍可完美访问,无需额外的工作。

1

指针p指向本地对象a,其生存期限制为try块。在那个街区外面,你有悬着的指针。因此导致段错误的未定义行为。