2016-09-28 44 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塊。在那個街區外面,你有懸着的指針。因此導致段錯誤的未定義行爲。