2013-07-02 91 views
0

我正在閱讀這篇文章(http://www.codeproject.com/Articles/627/A-Beginner-s-Guide-to-Pointers),它有一些代碼來解釋爲什麼我們應該使用它們。例如。動態分配。例如:指針 - 動態分配混淆

例如:不正確的程序:。


「該程序首先調用SomeFunction函數,它創建了一個名爲n已接收變量,然後使pPointer指向它然後,但是,是問題的所在。當功能葉, nNumber被刪除,因爲它是一個局部變量,當執行離開它們被定義的塊時,局部變量總是被刪除,這意味着當SomeFunction返回到main()時,變量被刪除,因此pPointer指向變量使用的地方是,不再屬於這個程序。「

#include <stdio.h> 

int *pPointer; 

void SomeFunction() 
{ 
    int nNumber; 
    nNumber = 25;  

    // make pPointer point to nNumber: 
    pPointer = &nNumber; 
} 

void main() 
{ 
    SomeFunction(); // make pPointer point to something 

    // why does this fail? 
    printf("Value of *pPointer: %d\n", *pPointer); 
} 

例2。正確的程序:


「當SomeFunction被調用,它分配一些內存,使pPointer指向它這一次,當函數返回時,新的內存保持不變,所以pPointer仍然指向一些有用的東西。 。這就是動態分配!「

#include <stdio.h> 

int *pPointer; 

void SomeFunction() 
{ 
    // make pPointer point to a new integer 
    pPointer = new int; 
    *pPointer = 25; 
} 

void main() 
{ 
    SomeFunction(); // make pPointer point to something 
    printf("Value of *pPointer: %d\n", *pPointer); 
} 

我的問題:


這上面的解釋做出完整意義上我,我感覺很好,爲什麼我們使用指針。然後我決定運行這些程序來看看會發生什麼。我期待第一個人爲* pPointer顯示一些隨機數,因爲這25個已被刪除。兩個程序都正確顯示「* pPointer的值:25」。第一個程序不應該像教程所說的那樣失敗嗎?

+0

[返回本地地址或臨時變量](http://stackoverflow.com/questions/2744264/returning-the-address-of-local-or-temporary-variable) – Lstor

+0

這是一個很好的解釋:http://stackoverflow.com/questions/ 6441218/can-a-local-variables-memory-be-accessible-scope-scope/6445794#6445794 – Lstor

回答

3

這是因爲它的未定義的行爲。幸運的是,printf函數沒有寫入該位置。

不錯事情(如果我可能是諷刺)關於未定義的行爲,是因爲它是未定義的,你不能真正知道事先會發生什麼。另見nasal demons

+0

從技術上講,pPointer將在printf()被執行之前解除引用,所以至少它是健壯的! – user1158559

+0

@ user1158559啊是的,這是正確的,這就是爲什麼它「工作」。 –

0

這兩個程序都正確顯示「Value of * pPointer:25」。第一個程序不應該是 ,因爲本教程會說它會失敗?

在第一個程序中,nNumber位於堆棧上。當SomeFunction()退出時,nNumber「超出範圍」,也就是說從程序的角度來看它不再存在。然而,用於該變量的內存仍然存在,並且它將包含與nNumber在範圍內時所做的相同的值,直到寫入一些新值爲止。 pPointer繼續指向該位置,當然,因此您可以繼續查看該內存的值。隨着其他函數的執行,該內存將最終用於某個新變量,並且值將會改變。危險是,如果您繼續使用pPointer期望它保持有效,您會發現它指向的值會不斷變化。

0

那就是未定義的行爲。沒有檢查來確保被取消引用的指針指向一個有效值。檢查this真棒的答案在這裏。

總之,

當變量超出範圍,任何事情都是可能的,其中變量以前存儲的位置(即使你做deletedelete只是釋放它不必然消滅它的內存) 。

它可能已被覆蓋,可能正在被覆蓋的過程中,或者至今沒有任何改變。 (就像你的例子)。因爲它在一個可以被你的代碼訪問的空間中,所以你沒有發現任何段錯誤等。

+0

感謝球員我現在明白爲什麼我們需要在這種情況下使用指針。 – user2364266

0

局部變量被分配在堆棧上。當函數退出時,指向堆棧頂部的指針被修改,以便局部變量離開堆棧,但堆棧未被擦除。因此,值25仍將位於pPointer指向的內存位置。如果使用局部變量調用另一個函數,則該內存將被覆蓋。 printf()將覆蓋位置,但在執行printf()之前,pPointer將在引用中用於參數。

0

第一個程序工作的原因是因爲在C++中使用指向已銷燬變量的指針是未定義的。但是C++沒有規定的是該內存會發生什麼。局部變量是使用C++中所謂的Stack Frame進行分配的,或者如果在函數完成後熟悉彙編語言「The Stack」,那麼經常存儲器並未被實際銷燬,而只是不能被覆蓋保護。所以一段時間指針可能工作,但在其他時間點,您指向的內存也可以被覆蓋。

這種現象的技術解釋是,當一個函數被輸入時,它的地址被壓入堆棧段。然後將局部變量定義爲該推送地址和堆棧指針之下的偏移量。這有效地爲您提供堆棧中的內存以訪問局部變量。但是一旦函數離開而不是浪費時間覆蓋內存,內存就不再受到保護,無法進行後期操作的讀取和寫入操作,因此行爲未定義,因爲我們不知道內存何時不再有效以及內存有多長是有效的並非一成不變,並經常波動。如果你正在尋找一個解釋這個視頻提供了一個很好的概述,而不進入核心的細節:http://www.youtube.com/watch?v=vcfQVwtoyHY

0

在第一個程序中,指針仍然指向內存中存儲數字25的位置。這是對的。問題不在於數字25被覆蓋;它的可能已被覆蓋。其他程序擁有免費的許可證,可以在不超出第一個程序的限制的情況下解決該內存位置問題,但是直到某些事情實際發生變化,硬件仍然存儲了數字25.