[英]Can static allocated memory become invalid during static deinitialization?
說我已經定義了一個像這樣的變量(C ++):
static const char str[] = "Here is some string data";
而且我有一個靜態分配的類實例,該實例在其析構函數中引用此數組,這會出錯嗎? 例如, str變量可能以某種方式變得無效嗎?
class A {
~A() {
cout << str << endl;
}
};
static A a;
我的假設是它不會出錯,但是我可以在任何地方清楚地指出它。 我想肯定知道這一點。 我的假設是,我們無法預測調用靜態分配的對象的析構函數的順序,但是直到該過程被拆除之前,才不會真正釋放數據本身。 指向POD的指針應該是安全的,但不是對象實例。
含義例如:
static const QString str = "Here is some string data";
要么
static const std::string str = "Here is some string data";
無法安全地在A的析構函數中使用,因為它們都在堆上分配了其字符串數據,並且在調用A的析構函數之前,析構函數可能會釋放它們。
我的假設是正確的,C ++標准中是否有任何部分對此進行了解釋,或者是否與其他可以驗證這一點的機構建立了鏈接?
始終自動定義自動,全局和靜態對象的析構函數的調用順序:這與構造函數的調用順序相反。 因此,如果對象A
引用了對象B
並且B
在 A
之前構造 ,則可以確保B
在 A
之后被破壞 。 這給我們留下了構造函數順序的問題。
這是我記得的內容:
main()
之前構造的。 我對其中一些內容有些模糊,因此,如果您認為這不正確,請更正我。
好吧,我嘗試自己閱讀C ++標准以找到一些答案。 從答案中可以看出,關於構造對象和分配對象之間的區別存在很多困惑。
從標准:
3.6.2初始化非本地對象
具有靜態存儲持續時間(3.7.1)的對象應在進行任何其他初始化之前進行零初始化(8.5)。 可以使用常量表達式(5.19)初始化具有靜態存儲持續時間的引用和具有靜態存儲持續時間的POD類型的對象。 這稱為常量初始化。 零初始化和常量初始化合在一起稱為靜態初始化。 所有其他初始化是動態初始化。 靜態初始化應在任何動態初始化發生之前執行。 對象的動態初始化是有序的或無序的。
我對此的解釋是,始終保證在運行任何構造函數之前已設置const char [] 。
3.6.3終止靜態存儲持續時間的初始化對象的析構函數(12.4)(在塊作用域或命名空間作用域聲明)是從main返回和調用std :: exit(18.3)的結果。 這些對象按照其構造函數完成或動態初始化完成的相反順序銷毀。 如果對象是靜態初始化的,則該對象的破壞順序與該對象被動態初始化的順序相同。
據我所知,具有常量表達式的POD類型將在任何對象類型之前進行初始化,並在任何對象類型之后進行銷毀。 這意味着在它們無效時,將不會運行任何可以訪問它們的代碼。
哪個應該解釋為什么Google的C ++代碼標准說您應該只使用帶有常量表達式的POD類型。 :
結果,我們只允許靜態變量包含POD數據。 此規則完全禁止使用vector(改為使用C數組)或string(使用const char [])。
如果我沒記錯的話,全局對象初始化未在標准中定義(或定義不充分),這使得全局對象難以相互引用。
如果您想確定初始化順序,請在其中使用帶有靜態對象的全局函數,然后將其返回。 現在,您將保證在第一個函數調用時將初始化靜態對象。
一旦脫離main(),銷毀將在應用程序末尾發生。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.