簡體   English   中英

Ruby - 清除所有全局變量

[英]Ruby - Clear all the global variables

我正在使用現有的框架進行並行執行。 這里使用了很多全局變量。 我可以看到一些全局變量(是的,我們應該避免它,但在這種情況下,我沒有選擇)正在產生問題。 global_variables顯示所有使用的全局變量的列表。 我想在每次執行結束時清除它們。 請問有什么建議嗎? ((

TL;博士

您不想清除所有全局變量,因為 Ruby 依賴於許多全局變量和常量才能正常運行。 不過,可以清除您定義的那些。

但是,您實際上不能取消定義全局變量,盡管您當然可以重新分配它們的值。 重構命名空間或詞法范圍的變量應該是一個長期目標,即使下面的建議現在對你有用。 傳遞綁定、值、配置設置和不依賴全局變量的對象引用有很多選項,在大多數情況下,減小變量范圍通常是正確的做法。

也就是說,這里有一些建議可能對您的情況有所幫助。 我還注意到一些邊緣情況可能適用於您的代碼,也可能不適用於您的代碼,但在處理頂級綁定和全局命名空間時,這些情況應該放在您的腦海中。

您不能取消定義或垃圾收集全局變量

根據定義,全局變量永遠不會超出范圍。 這也意味着變量本身也永遠不能被垃圾收集。

此外,與實例變量類似,但與類或局部變量不同,全局變量在引用時自動激活*nil ,以防止出現 NameError。 即使你從未真正定義過$foo$foo == nil #=> true


*作為一個微妙的區別, defined? $foo #=> nil defined? $foo #=> nil$foo = nil; defined? $foo #=> "global-variable" $foo = nil; defined? $foo #=> "global-variable" $foo = nil; defined? $foo #=> "global-variable" ,但我認為這對您的問題沒有任何實際影響。


如果您的主要目標只是“取消設置”全局變量的值,您可以執行以下操作:

NILABLE_GLOBALS = %w[$foo $bar $baz]
NILABLE_GLOBALS.map { eval "#{_1} = nil" }

雖然變量在技術上仍然是定義的,但實際上它們會以類似的方式響應未定義,例如等於nil

減少全局變量消耗的內存

這種方法還可以通過將全局變量全部指向一個單例對象(例如 NilClass 的唯一實例)來最小化全局變量的內存占用。 如果以前存儲在全局變量中的值在不再引用它們時被垃圾收集,這應該會減少內存使用量。 可能有幾個邊緣情況,比如存儲在 TOPLEVEL_BINDING 中的凍結字符串,我不確定這些值是否真的會丟失所有引用並因此被垃圾收集,但這更多的是內存管理問題而不是值分配或對象身份問題,如果內存是主要問題,那么您一開始就不會使用全局變量。

只要你不依賴defined? 重置值時返回nil ,這似乎是您最好的選擇,而不是重構代碼以使用可能超出范圍的變量。

額外注意事項

如果您使用的是無法垃圾收集符號的舊版 Ruby,請盡可能將 String 對象分配給您的全局變量。 如果您發現即使不再引用它們也沒有被垃圾收集,您也可以默認禁用凍結字符串。 如果內存過度膨脹,您可以在調用GC 模塊后檢查ObjectSpace以查找不需要的 Symbol 和 String 對象。 雖然這些對你來說不太可能是真正的問題,但如果是的話,至少你有一個起點。

在您的程序的某個早期階段,記錄 Ruby 解釋器本身提供的全局變量並將其存儲在一個常量中:

OrigGlobalVars = global_variables

我認為沒有辦法取消定義全局變量,但您可以通過執行以下操作將代碼創建的所有新變量設置為nil

(global_variables - OrigGlobalVars).each { |g| eval "#{g} = nil" }

這肯定會破壞一些使用全局變量的代碼,因為代碼可能沒有被設計為優雅地處理變量為 nil 的情況。 但是你可以在它們出現時修復它們。

暫無
暫無

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

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