簡體   English   中英

彈出堆棧時內存會怎樣?

[英]What happens to memory when stack is popped?

我有一個功能

public void f() {
    int x = 72;
    return;
}

因此x可能存儲在地址0x9FFF

函數返回后,該地址處的存儲器將如何處理? 還在嗎? 即該值仍然是72 還是完全無效?

彈出框架后,Java編程語言和Java虛擬機均未定義堆棧框架的內存發生了什么。 這是一個較低層的實現細節,被較高層的抽象所掩蓋。 實際上,Java語言和JVM字節碼使設計無法從堆棧中檢索已刪除的值(與C / C ++不同)。

但是實際上,Java中的堆棧框架的行為類似於C中的堆棧框架。不斷增長的堆棧將碰撞其指針(通常朝下)並分配空間來存儲變量。 縮小堆棧通常會向上移動指針,並簡單地將舊值保留在內存中以使其腐爛而不覆蓋它們。 如果您具有對JVM的堆棧內存區域的低級訪問權限,這是您應該期望看到的行為。

請注意,在Java中不可能像C這樣的技巧嘗試讀取未初始化的堆棧變量:

static boolean firstTime = true;

public void f() {
    int x;
    if (firstTime) {
        x = 72;
        firstTime = false;
    } else {
        // Compile error: Variable 'x' may not have been initialized
        System.out.println(x);
    }
}

在JVM實現中,其他堆棧行為也是可能的。 例如,當彈出框架時,可以將4 KiB虛擬內存頁面取消映射回操作系統,這實際上將擦除舊值。 同樣在機器架構(例如Mill)上 ,對堆棧存儲器也進行了特殊處理,從而使堆棧不斷增長將始終返回一個填充有零字節的區域,從而節省了從內存實際加載舊值的工作。

在C語言中,這是未定義的行為

在實踐中,如果您嘗試以下操作:

 int *ptr;

 void foo() {
    bar();
    printf("%d", *ptr);
 }

 void bar() {
     int x = 72;
     ptr = &x;
 }

然后,很可能是在C大多數實現, foo()將打印72 這是因為盡管ptr引用的地址可用於重新分配,但它尚未被重新分配,也沒有任何東西可以覆蓋該內存。 程序繼續運行的時間越長,初始化更多的局部變量並調用malloc() ,則該內存地址被重用的可能性就越大,並且該值將發生變化。

但是,C規范中沒有任何內容說明必須是這種情況-實現可以在范圍超出范圍時立即將該地址清零,或者在嘗試讀取它時使運行時出現恐慌,或者好吧,這就是“未定義”是什么意思。

作為程序員,您應注意避免這樣做。 很多時候,它會引起的錯誤會很刺眼,但是在某些時候,您會導致間歇性的錯誤,這是最難追蹤的錯誤。

在Java中,雖然超出范圍的內存可能仍包含72 ,但實際上無法訪問它,因此不會影響程序員。 在Java中訪問它的唯一方法是對它進行“正式”引用,在這種情況下,它不會被標記為垃圾回收,並且也不會超出范圍。

Java中的原始類型放在堆棧中(放入frame局部變量數組中)。 每次調用方法時都會創建一個新框架:

public void foo() {
    int x = 72; // 'x' will be stored in the array of local variables of the frame
}

當框架的方法調用完成時,該框架將被銷毀。 此時,所有局部變量部分結果可能仍駐留在堆棧中,但是它們已被放棄並且不再可用。

我不是在看副書,但我猜這在技術上沒有定義。

實際上,我曾經在C ++中嘗試過一次類似的事情,但如果我沒記錯的話,實際上是72 (或在函數調用返回之前放置的任何東西),因此機器實際上並沒有經過寫0到該位置或的東西。

其中一些也是實現細節。 我也用MIPS匯編語言實現了它(如果可以理解的話,我將包括一個代碼示例)。 基本上,當我需要寄存器時,我只是通過所需的許多局部變量來“增加”堆棧,將所需的當前值存儲在所需的寄存器中(以便以后可以恢復它們),然后重新使用寄存器。 如果是這樣的實現,則該值實際上可以包含調用方中的局部變量的值。 不過,我認為這並不是Java所做的。

TL; DR這是一個實現細節,但是至少在C語言中,直到真正需要它時,它才會覆蓋內存中的值。 Java很難預測。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM