簡體   English   中英

在C#中銷毀一個struct對象?

[英]Destroying a struct object in C#?

我有點困惑的是,在C#中只有引用類型被垃圾收集。 這意味着GC只選擇內存解除分配的引用類型。 那么值類型會發生什么呢?因為它們也會占用堆棧上的內存?

首先,它們是在堆棧還是堆的一部分取決於它們所屬的上下文 - 如果它們在引用類型中,它們無論如何都會在堆上。 (無論如何,你應該考慮你真正關心堆棧/堆分裂的程度 - 正如Eric Lippert寫的那樣,它主要是一個實現細節 。)

但是,回收上下文時基本上會回收值類型內存 - 因此當您從方法返回時彈出堆棧時,“回收”整個堆棧幀。 同樣,如果值類型值實際上是對象的一部分,則在該對象被垃圾回收時回收內存。

簡短的回答是你不必擔心它:)(這假設除了內存之外你沒有其他任何事情要擔心,當然 - 如果你有結構引用需要釋放的本機句柄,這是一個有點不同的情況。)

我有點困惑的是,在C#中只有引用類型被垃圾收集。

這不是事實。 或者說,這個陳述的真實性或虛假性取決於“收集垃圾”的含義。 垃圾收集器在收集時肯定會查看值類型; 這些值類型可能存在並保持引用類型:

struct S { public string str; }
...
S s = default(S); // local variable of value type
s.str = M(); 

當垃圾收集器運行時,它肯定會查看s,因為它需要確定s.str仍然存活。

我的建議:用動詞“收集垃圾”來准確澄清你的意思。

GC僅選擇內存解除分配的引用類型。

同樣,這不是事實。 假設你有一個實例

class C { int x; }

整數的內存將位於垃圾收集堆上,因此當C實例無根時由垃圾收集器回收。

為什么你會相信垃圾收集器只釋放引用類型的內存? 正確的說法是由垃圾收集器分配的內存由垃圾收集器釋放 ,我認為這是完全合理的。 GC分配它,因此它負責清理它。

那么值類型會發生什么呢?因為它們也會占用堆棧上的內存?

什么都沒發生在他們身上。 沒有什么需要發生在他們身上。 堆棧是一百萬字節。 堆棧的大小是在線程啟動時確定的; 它從一百萬字節開始,並且在整個線程執行期間保持一百萬字節。 堆棧中的內存既不會被創建也不會被破壞; 只是它的內容被改變了。

此問題中使用的動詞太多,如已銷毀,已回收,已取消分配,已刪除。 這與實際發生的情況不符。 一個局部變量根本不再是挪威鸚鵡風格

一個方法有一個單一的入口點,首先發生的是調整CPU堆棧指針。 創建“堆棧框架”,為局部變量創建存儲空間。 CLR保證將此空間初始化為0,而不是由於明確的賦值規則而在C#中強烈使用的功能。

即使方法代碼中包含多個return語句,方法也只有一個退出點。 此時,堆棧指針簡單地恢復到其原始值。 實際上它“忘記”了那里的局部變量。 它們的值不以任何方式“擦除”,字節仍然存在。 但它們不會持續很長時間,程序中的下一個調用將再次覆蓋它們。 CLR零初始化規則確保您永遠不會觀察那些不安全的舊值。

非常非常快,只需一個處理器周期。 C#語言中此行為的可見副作用是值類型不能具有終結器。 確保不必進行額外的工作。

當堆棧超出范圍時,堆棧中的值類型將從堆棧中刪除。

值類型一旦超出范圍就會被銷毀。

我會假設在執行堆棧幀后刪除堆棧幀時,將取消分配值類型

還要添加堆棧處於線程級別,堆處於應用程序域級別。

因此,當一個線程結束時,它將重新啟動該特定線程使用的堆棧內存。

.NET中的每個值類型實例都將成為其他內容的一部分,這可能是更大的封閉值類型實例,堆對象或堆棧幀。 每當這些東西出現時,其中的任何結構也會形成; 只要包含它們的東西確實存在,那么這些結構將繼續存在。 當包含結構的東西不再存在時,結構也將如此。 沒有破壞容器就無法破壞結構,並且沒有辦法破壞包含一個或多個結構的東西而不破壞其中包含的結構。

暫無
暫無

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

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