2015-09-30 87 views
1

編輯:有關此問題代碼工作原因的問題已通過重複標記中的鏈接問題得到解答。關於字符串文字生存期的問題在這個問題的答案中得到了回答。const char * value lifetime

我想了解如何以及何時const char *指向的字符串被取消分配。

考慮:

const char **p = nullptr; 

{ 
    const char *t = "test"; 
    p = &t; 
} 

cout << *p; 

離開內部範圍後,我希望p是懸空指針const char *。但在我的測試中,它不是。這意味着即使在t超出範圍之後,t的值實際上仍然有效且可訪問。

這可能是由於通過將其綁定到const引用來延長臨時的生命週期。但我不這樣做,即使將參考文獻t保存在一個成員變量中,稍後從不同函數打印值仍然會給我它的正確值。

class CStringTest 
{ 
public: 
    void test1() 
    { 
     const char *t = "test"; 
     m_P = &t; 
     test2(); 
    } 

    void test2() 
    { 
     cout << *m_P; 
    } 

private: 
    const char **m_P = nullptr; 
}; 

那麼t的價值在這裏的壽命是多少?我會說我通過取消引用一個指向超出範圍的變量值的指針來調用未定義的行爲。但它每次都有效,所以我認爲情況並非如此。

當嘗試一些其他類型的像QString

QString *p = nullptr; 

{ 
    QString str = "test"; 
    p = &str; 
} 

cout << *p; 

代碼始終打印值也正常,即使它不應該。 str以其價值超出了範圍,並且我也沒有通過將其與常量參考綁定來延長其壽命。

有趣的是,帶有QString的類示例的行爲與我所預期的相同,test2()會打印亂碼,因爲該值確實超出了範圍,m_P成爲懸掛指針。

那麼const char *的實際使用壽命值是多少?

+4

您無法測試是否有什麼懸掛。任何嘗試這樣做都會有不確定的行爲。 –

+3

這基本上是一個重複http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope與一個問題關於字符串文字的生命期 –

+0

_「在我的測試中,它不是」_LOL你什麼? –

回答

4

變量pt是您聲明的堆棧變量,因此它們的生命週期結束於其封閉塊的末尾。

t的值是字符串字面值"test"的地址,並且這不是您聲明的變量,它不在堆棧上。它是一個字符串文字,它是程序中定義的常量(類似於整數文字99或浮點文字0.99)。文字不會像你期望的那樣超出範圍,因爲它們不會被創建或銷燬,它們只是

標準表示:

評價在具有靜態存儲持續時間的字符串文字對象,如上述規定的從給定的字符初始化的字串文本結果。

使編譯器創建代表字面"test"具有靜態存儲時間,這是相同的持續時間和全局變量static,這意味着它不會超出範圍像堆棧變量的對象。

p的值是t地址,這確實當t超出範圍成爲無效的指針,但這並不意味着存儲在該地址的值突然變得不可訪問或已被清除。表達式*p是未定義的行爲,但它似乎工作,因爲沒有重用內存位置,所以*p仍包含字符串文字的地址。有關更多細節,參見頂部答案Can a local variable's memory be accessed outside its scope?

3

編譯器把文字串到被加載到虛擬存儲器的受保護節段靜態分配空間,使得這些字符串可以在該方法的整個壽命共享(這個值是一個常數,所以不需要花費不斷的開銷來讓它們存在)。尋找類似被釋放的東西是浪費時間,因爲它從來沒有真正發生過。

變量是堆棧分配的。字符串常量應該被認爲是:字符串常量...類似於數字3.

0

字符串文字在靜態存儲中分配。

如果你提到一個字符串在程序中任何地方的文字,這是因爲如果你做的事:

static const char someUniqueIdentifier[]="the data"; 
在全球範圍內

const char* str = "some string";表示確保"some string"存在於程序的靜態部分中的常量空終止數組,並指向str

然而,你在第一個例子中引用了你的自動(=在堆棧上)指針,而不是靜態存儲字符串。這確實有一個侷限於它的範圍,但是當你調用test2()時,test1()的範圍尚未結束。