2016-11-04 103 views
0

在C++程序中,常量數據存儲在哪裏,特別是字符串常量?存儲在內存中的字符串常量在哪裏?

我問,因爲在以下問題:

Why can creating a static const std::string cause an exception?

由達蒙答案,在末端執行以下操作:

一個string_view意志,違背了一個字符串,而不是分配非常量內存,將常量數據複製到該內存中,然後假裝它是不變的。相反,它將直接管理一個指向常量數據的指針,而這就是全部。

這樣,你的常量是真正的(不只是正式)常量,有 沒有分配,沒有例外的可能性,沒有雙重記憶 用法。大多數情況下,它仍然看起來像一串字符串。 唯一值得注意的區別是,一個string_view不 保證nul終止(但它指向 的字符常量沒有,所以這是無關緊要的),並且它真的是不變的事實, 不可修改......這是正是你想要的。

甚至不需要將常量存儲在內存中的某些地方?如果它們存儲在內存中(因爲內存是有限的),是不是可能會拋出一個異常,因爲沒有更多的內存?

+2

它們的內存在任何代碼運行之前加載。所以沒有運行時異常是可能的。如果你可以運行,那麼內存已經在那裏。 –

+1

相關http://stackoverflow.com/questions/349025/is-a-string-literal-in-c-created-in-static-memory也https://isocpp.org/wiki/faq/ctors#static-初始化階 –

回答

2

問題是std::string是一個對象,而不僅僅是普通數據。

這意味着,當你聲明

static const std::string foobar = "foobar"; 

即在二進制保留的靜態數據是一個針對字面"foobar"(打算作爲const char*)和用於存儲std::string對象所需的空間,這是不是存儲其內容所需的空間。

想象一個std::string,就像這樣,讓我們​​說

class string { 
private: 
    size_t length; 
    char* data; 

public: 
    string(const char* data) : length(strlen(data), data(new char[length+1]) { 
    strcpy(this->data, data); 
    } 
    ~string() { delete data; } 
}; 

這是一個微不足道的不安全的代碼,但它只是給你的想法。當你有你的static std::string時,所需的唯一空間是sizeof(char*)+sizeof(size_t)字節,因爲數據本身是在堆上動態分配的。

這就是爲什麼使用static const std::string浪費兩倍的空間:對於傳遞給字符串構造函數的文本本身以及std::string

現在這個對象在編譯時不是「預構造」的。它是在運行時構建的,標準的doesn't guarantee你恰好發生了這種情況(事實上,如果它發生在調用main之前,你無法捕獲構造函數可能拋出的任何異常)。

所引用string_viewconst char*周圍的包裝,其好好嘗試浪費存儲器,因爲它僅存儲一個指針的內容,這是不用於正常std::string其被設計成是可變的情況。

1

靜態常量存儲在可執行文件的「數據」段中。它們的存儲位置可能因系統而異,但以Linux爲例,它們作爲可執行文件的一部分加載,並立即出現在進程內存映射的「文本段」之上。

它們在程序開始執行之前由操作系統加載到進程內存映射中;因此,如果他們沒有足夠的內存,程序甚至無法加載,更不會拋出異常!

如果您對流程的內存佈局感興趣,我發現this blog post是最有幫助的。