2014-10-29 79 views
2

我感到困惑野指針和野指針的一些細節,這裏是我的代碼:爲什麼懸掛指針可以繼續訪問對象?

#include <iostream> 
using std::cout; 
using std::endl; 

class A 
{ 
public: 
    void Func() { cout << "Func of class A, the address is:" << this <<endl; } 
}; 

void Test(void) 
{ 
    A *p; 

    //get an error in VS2013 because of uninitialized pointer. 
    //But it's ok in g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2 
    p->Func();  // wild pointer, ((1)) 

    { 
     A a; 
     p = &a; 
     p->Func(); 
    } 

    p->Func(); //dangling pointer ((2)) 
} 

int main() 
{ 
    Test(); 
    return 0; 
} 

結果就像如下:
的Windows:
Func of class A, the address is:003CFD47 Func of class A, the address is:003CFD47

Ubuntu的:
Func of class A, the address is:0xb74ef39d Func of class A, the address is:0xbff85a3b Func of class A, the address is:0xbff85a3b

我的問題:
(1)g ++編譯器讓wil在((1))處傳遞e指針,即使運行代碼,它似乎指向'某個對象'。爲什麼會這樣呢?它是編譯器的錯誤嗎? (2)據我所知,在塊句之後,p將是((2))處的懸掛指針。但爲什麼可以繼續指向Func()?由於對象a佔用的空間不會被其他應用程序覆蓋嗎?

+3

這是不確定的行爲。 – 2014-10-29 08:02:44

+0

這是?懸掛指針?@πάνταῥεῖ – kkwang 2014-10-29 08:03:34

+1

@wjk訪問/取消引用它。 – 2014-10-29 08:04:13

回答

4

p最初是未初始化的,因此它包含發生在調用堆棧區域的任何隨機值,這些值是爲p保留的。這就是你在第一個cout輸出中看到的結果。

然後,您創建一個對象並將其地址分配給p,您將在第二個cout輸出中看到該對象。

然後該對象超出範圍並被釋放,但您不會重新分配任何內容到p,因此它攜帶其現有值,您在第三個cout輸出中看到該值。

當通過無效指針調用對象方法時,雖然技術上未定義的行爲,但通常沒什麼不好的情況會發生,只要您不取消引用訪問該類的任何成員的指針,包括需要VMT指針的任何虛擬方法。

一個方法調用實際上只是一個函數調用一個額外的隱藏this參數,所以你的示例代碼是真正在做從編譯器的角度來看,以下幾點:

#include <iostream> 
using std::cout; 
using std::endl; 

class A 
{ 
public: 
    static void Func(A* this) { cout.operator<<("Func of class A, the address is:").operator<<((void*)this).operator<<(&endl); } 
}; 

void Test(void) 
{ 
    A *p; // initialized with random value 

    A::Func(p); 

    { 
     A a; // note: allocates only 
     A::A(&a); // then constructs 
     p = &a; 
     A::Func(p); 
     A::~A(&a); 
    } 

    A::Func(p); 
} 

int main() 
{ 
    Test(); 
    return 0; 
}