2017-07-25 88 views
-1

我正在閱讀有關Dispose模式並碰到如何memory is allocated。以下是http://codebetter.com/karlseguin/2008/04/28/foundations-of-programming-pt-7-back-to-basics-memory/的報價。如果大部分數據都堆在堆棧上,堆棧內存的主要重要性/作用是什麼?

內存分配
....
....
唯一的例外是屬於引用類型值類型 - 例如用戶類的Id特性的推移的堆以及User類本身的實例。

這裏也提到了Stack Overflow的問題。 memory allocation for value type inside reference type in .net

我的理解是,所有值類型與它們聲明的位置無關,都會疊加。現在看起來錯了。在下面的代碼中,i將堆積如山;根據鏈接不在堆棧上。這是因爲MyClass是引用類型,它將與堆一起堆棧,並且它的所有值類型。

class MyClass() 
{ 
    int i = 5; 
} 

好吧,所以只有值類型那些不是類的一部分,然後轉到堆棧內存。對?但是,像C#這樣的DotNet語言中的幾乎所有內容都在課堂內。那麼到底什麼去堆棧內存?

這個answer解釋了什麼值類型堆。

如果是這種情況,那麼堆棧內存上的內存很少甚至幾乎沒有。

我懷疑我誤解了一些東西。

如果幾乎所有的數據都進入堆內存,我不明白堆棧內存的重要性和作用。

請解釋。


以下兩篇文章以簡單的方式解釋了關於內存管理的很多內容。

https://blogs.msdn.microsoft.com/ericlippert/2009/04/27/the-stack-is-an-implementation-detail-part-one/

https://blogs.msdn.microsoft.com/ericlippert/2009/05/04/the-stack-is-an-implementation-detail-part-two/

+0

堆棧主要用於局部變量並跟蹤調用樹中的這些變量。 – juharr

+2

閱讀Eric Lippert的[堆棧是一個實現細節](https://blogs.msdn.microsoft.com/ericlippert/2009/04/27/the-stack-is-an-implementation-detail-part-one/) 。 –

+0

堆棧是有用的,因爲它推動和彈出。這是不小的優勢。這就是爲什麼*是堆棧。它*發生*有時也在內存分配方案中有用 - 並從那裏Eric Lippert的解釋進來。 –

回答

9

不要把它想成 「棧」 和 「堆」。將其想象爲短期記憶長期記憶。現在很容易知道堆棧上發生了什麼以及堆中發生了什麼。 變量的生存期是否比當前方法的激活時間長?如果是的話,那麼它不是短命的,而必須堆積如山。如果是,那麼可以進棧。

例如:

class C { 
    void M() { 
    string s = Whatever(); 
    Something(s); 
    } 
} 

局部變量s可以去在短期池,因爲它不會持續長於方法激活。

現在,你可能會說等一下,string是一個引用類型,所以它肯定會堆在堆上。不,它不是。 字符串放在堆上,但該變量不包含字符串。字符串是一個引用類型,所以該變量包含引用引用可以在棧上。它是指的是在堆上,但參考本身是一個值,並且可以在堆棧上。

因此,不要以爲任何東西的類型決定了它的存儲位置。該類型是無關緊要的。價值類型或參考類型的變量如果壽命短,可以在短期內匯入,如果不是,則必須長期匯入。

現在來談談

class C { 
    void M() { 
    int i = Whatever(); 
    X(() => i) 
    } 
} 

現在我可以進入堆疊?編號X可以存儲傳入的委託的副本,並且該委託需要知道i的值,因此該變量需要比方法M的激活壽命更長,因此i會長期存在。 i在這裏堆。

同樣,它是一個int的事實是完全不相關的。這是一個變量,它生活很長時間,所以它堆積如山。

怎麼樣一個類的字段或數組的元素?那些是變數。只要類實例或數組實例存在,它們就會生活,因此它們的生命週期是不可預測的,因此它們會長期存在。

爲什麼我們有一個短期池和一個長期池?因爲短期池的垃圾回收器是極其便宜的相對於長期池的垃圾回收器而言便宜且便宜。因此,我們希望可以選擇在短期池中生成變量 - 這是當它們的壽命是

+0

「......它指的是堆......」 - 爲什麼?它總是保證在堆中分配嗎?如果我有一個'Tuple '(引用類型),爲什麼需要在堆中分配? –

+2

@LucaCremonesi:因爲所提到的事情*不知道有一個短的生命*。現在,有些場景我們可以知道在方法中創建了一個特定的引用,從不會轉義該方法,因此在該方法返回後仍未使用。在這些情況下,CLR *可以生成對堆棧中某些東西的引用。目前的實現不這樣做;只有一個分配器和收集器用於參考類型會更便宜,更容易。但是*原則上*不反對參考類型的短命例。 –