2016-12-06 59 views
-1

說我有一個指針char* ptr分配的內存和另一個指針char* arr = ptr狀態,如果內存被釋放

ptr內存被釋放後會發生什麼arr

讓功能是:

char* foo() 
{ 
    char* ptr = new char [100]; 
    char* arr = ptr; 
    delete [] ptr; 
    return arr; 
} 

我可以使用這個返回的值?

它會導致任何編譯時/運行時錯誤? 或其他任何東西。如果函數

char* foo() 
{ 
    char* ptr = new char [100]; 
    char* arr = ptr; 
    delete [] arr; 
    return ptr; 
} 

我想就沒有從以前的輸出變化,但會有任何變化

還是會發生什麼?

會發生什麼,如果我有一個類

class Pointer 
{ 
    public: 
    char* ptr; 
    Pointer() 
    { 
     ptr= new char [100]; 
    } 
    ~Pointer() 
    { 
     delete [] ptr; 
    } 
}; 

和功能

Pointer foo() 
{ 
    Pointer ptr; 
    ptr.ptr[0]='l'; 
    return ptr; 
} 

慣於在析構函數結束時調用,並創建一個懸空指針Pointer::ptr

+0

「我可以使用這個返回的值嗎?」你可以但它可能不聰明,它可能是一個懸掛指針。也許如果你期待一個空的返回值,只需返回null或null'arr'。 – George

+0

arr指向垃圾。不要歸還它。 – AndyG

+1

我想你問的是錯誤的問題。 'arr'完全沒有任何事情發生。或者'ptr'就是這個問題。 – juanchopanza

回答

4

我可以使用這個返回值嗎?

您可以「使用」它,但無法取消引用它。你可以,例如,打印指針值了(而不是指向的數據!):

std::cout << (intptr_t)foo() << std::endl; // OK 
std::cout << foo(); // WRONG: this dereferences the pointer! 

因此,儘管該值可以是「拿來主義」,它不是一個指針char真正有用的了。

還是會發生什麼,如果函數是[...]

兩個函數具有相同的含義。在任何體面的編譯器上,編譯時您都應該期望得到yield identical machine code

arrptr後會發生什麼情況?

沒有任何反應:它的值保持不變。但是因爲指向的對象已經被釋放,所以它現在是一個懸掛的指針。所以你不能用它做任何事情:如果你這樣做,你會得到未定義的行爲。未定義的行爲意味着任何事情都可能發生。這包括:沒有任何事情發生(事情「出現」到「正常工作」),或者讓您的硬盤格式化。

情況是一樣的,如果你建很多房子。你給你的朋友Arr的GPS座標。但在此期間,你決定搬出去。然而你的朋友Arr仍然有舊座標。現在Arr決定使用它們。有幾種可能的結果 - 你無法控制發生哪一種結果。我會列舉幾個:

  1. 你搬了一小時前。一切都是一樣的。阿爾走過去,拍了一張你的舊房子的照片,然後離開了。

    這對應於由於巧合,指向的存儲器仍然包含可用內容的情況。你仍然有一個錯誤,但巧合隱藏它。

  2. 你搬走了,但第二天該市決定夷平了很多,建立在它和鄰近的許多大的公寓大樓。你的朋友來期待一個小房子,看到一個大公寓高樓,並最終完全傾倒。

    這對應於內存得到重用並隨後是懸空指針解引用的情況。這是否會導致CPU引發異常取決於之前存在的對象類型。

  3. 你搬走了,但有一個大地震,現在有一個湖那裏。你的朋友陷入溺水。

    這對應於曾經是自由存儲區的一部分的虛擬存儲器的現在冗餘塊一直未映射的情況。你得到一個頁面錯誤。

    內存管理器運行時可以取消分配用於備份指針所指向的地址空間的頁面。回想一下,C++程序經常在虛擬內存機器上運行。程序看到的地址空間是虛擬地址空間。如果沒有物理內存頁面支持給定的虛擬地址空間頁面,並且沒有該頁面的文件或其他支持,則對其進行的任何訪問都將導致傳播到userland的頁面錯誤,並在未處理時終止進程(因爲它是默認設置) 。

+0

您可以使用它指向其他位置,或將其設置爲'nullptr'。 – juanchopanza

+0

我明白了參考文獻1和2,但是什麼是3 – WARhead

+0

它也可以爲時間旅行創造很多樂趣,某些平臺可能通過重新映射導致違規的頁面的分頁版本來處理訪問衝突。這可能會導致過時的數據在沒有程序注意的情況下發生。長話短說:未定義的行爲是不確定的,應該不惜一切代價避免。 – Mgetz

0

從你的代碼中,arr會指向沒有分配內存,所以如果你嘗試使用它,它將包含絕對的隨機數據。

+0

這不是真的,事實並非如此,可能對嵌入式編程等有用。 – George

+0

嵌入式編程不會真的打擾有人問這樣簡單的問題,如什麼指針指向後,它的目標被釋放... –

0

我曾經在嵌入式系統上,並且,運氣有時會發生,我不得不附近在正確的時間正確的地點連接調試器(相對於刪除),當系統崩潰。代碼是C++,調試器是gdb,vxWorks是嵌入式系統工具套件。

我檢查的代碼是類似於你的問題的一些方式,本質上是指針的取消引用刪除後發生。

... 
    char* ptr = new char [100]; 
    delete [] ptr; 

    // more stuff that did not affect what ptr pointed to 

    // about 5 to 9 lines later 
    char retVal = ptr[x]; // <<< invalid access crash 
... 

該崩潰表明ptr [x]無效。

嵌入式系統(VxWorks的),有技術,以確認其中ptr指向確實不再背景下,從任務未映射。

我猜這是不尋常的(因爲性能),但刪除不僅從動態內存中釋放塊,而且還從線程內存空間釋放內存塊,使地址無效,導致總線錯誤。

我不知道如何確認Linux中的類似信息。


會發生什麼PTR內存被釋放後arr中?

自動變量不受刪除的影響。


我可以使用這個返回的值?

行爲是未定義的(即UB),所以您應該避免這樣做。


會造成任何編譯時/運行時錯誤?或者其他任何事情。

UB意味着任何其他事情都可能發生。

+0

請重新審視我添加了一些疑惑的問題 – WARhead