2014-07-23 57 views
1

當我試圖運行此我得到一個分段錯誤:局部數組變量的最大大小

#define FILE_NAME "test.html" 
#define STRING_ARRAY_SIZE 1000000 

int main() { 
fstream file; 
string line = ""; 
string string_array [STRING_ARRAY_SIZE]; 
int i = 0; 

file.open(FILE_NAME); 
while(getline(file, line)) { 
    string_array[i] = line; 
    i++; 
    cout << line << endl; 
} 

file.close(); 
} 

相反,當我嘗試編譯這一點,它的工作原理:

#define FILE_NAME "test.html" 
#define STRING_ARRAY_SIZE 100000 

int main() { 
fstream file; 
string line = ""; 
string string_array [STRING_ARRAY_SIZE]; 
int i = 0; 

file.open(FILE_NAME); 
while(getline(file, line)) { 
    string_array[i] = line; 
    i++; 
    cout << line << endl; 
} 

file.close(); 
} 

原來,唯一的區別是數組的大小。爲什麼它在100000時工作,而不是在1000000時?什麼是最大尺寸?謝謝。

+2

將局部變量(包括數組)放在堆棧上,該堆棧的大小有限。在使用VC++的Windows上,默認情況下爲1MB,在Linux上通常爲8MB。試圖在堆棧上分配更多的數據將導致*堆棧溢出*,這會導致未定義的行爲並且很可能導致崩潰。數組中最大數量的成員不是固定的,而是取決於數據的大小和剩餘的堆棧大小。 –

+2

在編譯期間,你真的得到了分段錯誤**嗎?這意味着編譯器會有一個錯誤,或者類似缺陷的內存......可能不是,但它可以更清楚地說明問題。 –

+0

ups你們是對的。運行時發生分段錯誤:) – user3289157

回答

2

該限制是系統(不僅是硬件,還包括軟件,特別是操作系統和運行時)。另見this question與你非常相似。

你應該儘量避免太大call stack frames。現在在臺式機或服務器機器上,我會推薦最多幾十千字節用於最大的調用堆棧幀(並且通常少得多,即數百字節) - 特別是對於中間非葉或遞歸函數。一個典型的系統有一個機器堆棧可以增長到幾兆字節(但在嵌入式微控制器上,或在Linux內核中,可能只有幾千字節!)。對於多線程應用程序,應該少一些(因爲每個線程都有自己的堆棧)。

在Linux和POSIX系統,你可以使用系統調用setrlimit(2)較低RLIMIT_STACK(也許有時略有增加)堆棧限制。在帶有bash外殼的終端中,使用內置的ulimit -s

GCC選項會感興趣:-fstack-usage-Wframe-larger-than=-fstack-split

在代碼中,考慮與

vector<string> string_vector; 

更換

string string_array [STRING_ARRAY_SIZE]; 

和更換

string_array[i] = line; 
i++; 

string_vector.push_back(line); 
3

C++沒有設置限制,而是設置限制並取決於您正在使用的硬件。基本上你可以說對於用於定義數組的索引的類型設置了兩個限制(可以使用std::size_t來檢查它可以佔用的大小),第二個限制是物理內存限制。

實際上內存分配在兩個地方,第一個在堆上(動態分配的內存)。這裏的大小限制基本上是可用硬件和操作系統模擬空間的能力的組合。第二個是堆棧(本地聲明的變量)。這裏的大小限制是編譯器定義的。

+0

限制通常由軟件設置。看到我的答案(和Linux上的「setrlimit」)。 –

1

這可能是2件事。

首先,你需要內存來加載程序中的東西。所以,如果你沒有足夠的內存,你將有一個Segmentation fault。你不能保留1000000,但你有足夠的內存來保留,例如,100000.

其次,看看size_t的參考。每個對象都有一個限制來表示它的數據。

1

首先:在編譯的時候你不能有段錯誤,在編譯的時候,它被稱爲「編譯錯誤」,而上面的代碼看起來是正確的。

和往常一樣:這取決於。內存堆棧有限制,它取決於平臺。