簡體   English   中英

靜態取消初始化期間,靜態分配的內存會變得無效嗎?

[英]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 之后破壞 這給我們留下了構造函數順序的問題。

這是我記得的內容:

  1. 全局和靜態對象是在調用main()之前構造的。
  2. 類本地靜態變量在其類的任何對象之前構造。
  3. 首次達到它們的作用域時,將構造函數局部靜態變量。
  4. 相同翻譯單元中的全局和靜態對象是按定義順序構造的。 (這意味着標頭的包含順序可能會影響此!)
  5. 跨翻譯單元的全局和靜態對象的構造順序是不確定的。

我對其中一些內容有些模糊,因此,如果您認為這不正確,請更正我。

好吧,我嘗試自己閱讀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.

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