2015-09-01 133 views
1

我正在嘗試創建一個int整型向量的數組,但是我在這段代碼中遇到了一個段錯誤。爲什麼此數組分配會導致段錯誤?

int main() { 
    vector<int> x[1000000]; 
} 

我認爲這是因爲我超過了堆棧大小,所以我使用動態分配,它似乎解決了這個問題。但是,爲什麼這樣工作:

vector<int> x[1000000]; 

int main() { 
    // do nothing 
} 

和這項工作?

int main() { 
    static vector<int> x[1000000]; 
} 
+1

這是因爲變量分配在數據段上,而不是堆棧上 –

+0

因此,全局變量和靜態變量總是分配在堆上? – CSGregorian

+3

看一看程序解剖學的[this](http://static.duartes.org/img/blogPosts/linuxFlexibleAddressSpaceLayout.png)圖像。在你的第一個實現中,內存分配在堆棧上,根據圖片,它有8MB的限制(不同的機器可能有不同的限制)。數據段大於8MB,因此在嘗試分配這種矢量時不會出現錯誤 –

回答

2

這是因爲數組在第一個示例中分配在堆棧上,並且您的實現對可用堆棧施加了太嚴格的限制。你的第二個例子可能已經純粹運氣成功了。

請參考this picture關於您的程序內存的正常佈局,訪問白色區域可能會導致分割錯誤(無論如何,這是一個壞主意)。

現在,當你分配一個非靜態局部變量時,直接數據將被分配到棧上,但構造函數也可以通過new在堆上分配空間。在你的情況下,構造函數可能也會分配內存(vector的直接數據可能只有一個指針,但是你分配了其中的數百萬,因此至少有8Mb的直接數據)。它可能是構造函數的存在,實際上會使程序發生段錯誤,因爲堆棧中分配的空間可能是未訪問的(這是您實際訪問堆棧限制之外的空間時會發生段錯誤)。

當您分配靜態數據或全局數據時,直接數據會分配到數據或BSS段中,如果預啓動數據(即構造函數之前的數據如果有的話)爲零,它將被置於BSS段。在你的情況下,數據可能會被放置在BSS中。

現在請注意,對於全局分配,構造函數將在到達main之前運行(而不是靜態的,直到第一次調用該函數纔會運行),但是您可能已通過構造函數中的new動態分配並且在main之前調用new意味着未定義的行爲,那麼您應該認爲自己很幸運,第二個示例沒有失敗(它可以在沒有事先通知的情況下這樣做)。

從中學習的教訓是,如果不需要複雜的構造函數,則最好將大數據放在全局範圍中。如果你需要一個複雜的構造函數,你最好通過new動態分配它。你當然可以把它作爲本地的static,並在全局需要時返回對象的引用。

相關問題