2009-08-22 66 views
0

我是C++的新手,我不知道從哪裏開始,所以我上傳了代碼到pastebin,因爲它有很多。在C++中的隨機段錯誤

該代碼編譯良好,即使使用gcc的-Wall選項也不會發出警告。

它應該生成所有素數達到給定數量作爲命令行參數。

對於較小的數字(例如4,000或5,000),它工作正常。在更大的數字上,如400萬,幾乎所有的時間都會出現段錯誤。在兩者之間的數字中,它是否被擊中或未命中。

+0

這真的不是問題。 換句話說,有人可能會幫助你。 – EvilTeach 2009-08-22 21:54:20

+0

嘗試附加到調試器或使用cout語句來查看是否可以找出段錯誤發生的位置。 – theycallmemorty 2009-08-22 21:54:23

回答

10
int primes[max]; 

prime = primes; 
while(*prime) { 
    *prime = 0; 
    prime++;  
} 

在前面的代碼,你可以通過隨機存儲器輕鬆運行,基本上你正在經歷的RAM,直到找到一個0.如果您的數組中沒有0那麼它會碰到內存不不屬於該過程並且會發生段錯誤。

編輯:正如Alcon指出的那樣,您在代碼的其他地方也是這樣做的。

最好不要在堆棧上分配素數,因爲你不太可能擁有那麼多的堆棧內存。

要解決這個問題試試下面的代碼,而不是

int primes = new int[max]; 

size_t count = 0; 
while(count < max) 
{ 
    prime[count] = 0; 
    count++;  
} 

而且不要忘記調用delete []素數;在你的代碼的末尾(當你與素數陣列完成)

+0

這一個應該贏。 – ebo 2009-08-22 22:01:24

+2

在這一點上素數的內容還沒有初始化,所以(因爲int是一個沒有默認構造函數的主要類型等等),它將是未定義的;是否存在零或是否存在一點隨機。 – Will 2009-08-22 22:02:54

1

您正在堆棧上分配數組。堆棧的大小有限,可能會溢出。

試着用new/delete分配你的數組。

+2

更好的是,使用一個向量,以便您不會分配更多的內存。 – 2009-08-22 21:58:17

+0

雅這絕對是一個向量的正確情境,你分配的內存比你需要的多得多。 – DeusAduro 2009-08-22 22:00:08

+0

溢出是從不檢查長度,而不是它在堆棧上,特別是? – Will 2009-08-22 22:01:40

0
int primes[max]; 

在堆棧中分配巨大的數組是不好的,因爲默認情況下,堆棧的大小很小。最好在堆中分配素數[]。

+1

崩潰有可能發生在未初始化的緩衝區上的「while(* prime)」循環中;把它放在堆上不會改變這一點。 – Will 2009-08-22 22:01:06

+1

你是對的意志。無論如何,在堆棧中分配巨大的內存塊是一個額外的缺陷。 – 2009-08-22 22:04:36

1

好一兩件事,這是有問題的:

int sum_array(int num_array[]) { 
    int current_total = 0; 
    int *iptr = num_array; 
    while(*iptr) { 
     current_total += *iptr; 
     iptr++; 
    } 
    return current_total; 
} 

它說的是在開始您將得到數組的開始。當內存塊中的值大小不爲零時,移至下一個內存塊。這裏發生的事情是它會繼續走過你的數組的末尾,最終搞亂內存,它不應該是導致段錯誤的原因。它似乎是隨機的原因是,有時在數組末尾的內存是空的,這將工作正常。但有時它不是,然後它訪問內存,它不應該和CRASH。

這可能不是唯一的問題,但它是我注意到的第一個問題。要修復它,請記錄數組的大小,將它傳遞給函數,然後使用for循環來迭代它,而不是使用指針。像這樣:

int sum_array(int num_array[], int arraySize) { 
    int current_total = 0; 
    for(int i = 0; i < arraySize; i++) { 
     current_total += num_array[i]; 
    } 
    return current_total; 
} 

我會再看看是否還有其他東西。

編輯:

在第二次看,你在其他兩個地方同樣的事情。在這裏:

while(*prime) { 
     cout << *prime << " "; 
     prime++; 
    } 

在這裏:

while(*prime) { 
    *prime = 0; 
    prime++;  
} 

在這兩個地方我敢打賭美元,你超越你的陣列甜甜圈而這是什麼引起的段錯誤。如果你是新手,我強烈建議不要使用指針算法來遍歷你的數組。堅持良好的舊for循環,並跟蹤for循環的結束。其他人建議從堆而不是堆棧分配數組。對於一個龐大的陣列來說,這是一個好主意,但是,至少在我的經驗中,堆棧溢出通常不會導致段錯誤。編譯器通常會在您分配的空間多於堆棧中的空間時注意到。仍然我會建議使用一個向量(對於作業中的額外功勞,請參閱是否可以使用分配爲堆中指針數組的雙指針來實現自己的向量))或者僅使用std: :向量。這是一個可擴展的數組,它可以讓你在你找到數組時添加素數而不是分配你不一定需要的整個空間。

1

你應該動態地分配你的素數的陣列,primes,即:

int* primes = new int[max]; 

你的程序應該甚至不應該作爲編譯是。祝你的功課好運!

+0

我相信動態大小的堆棧數組是g ++的擴展。但是,是的,它不符合標準的C++。 – 2009-08-22 22:02:55

1

其他(例如Goz)已經提供了正確的答案 - 未初始化變量的值不能被依賴,因爲它們隨着運行而變化。正如其他人指出的那樣,在堆棧上分配大型數組也是有風險的,因爲堆棧空間通常比堆空間更稀少。

作爲一個側面的問題,以與primes[max]相同的方式分配可變大小的數組不是符合標準的C++,而是一個g ++擴展,因此您的代碼不可能與其他編譯器一起工作。您可以使用newdelete來代替 - 但在這些情況下更好地使用vector<int>,因爲它會爲您執行清理。

[編輯:謝謝你會爲指出麻煩的真正根源是在其他地方。]

+1

雖然它是正確的診斷? – Will 2009-08-22 22:08:30

+0

你是對的 - Goz的答案更可能是真正的原因(儘管在堆棧中分配大型陣列仍然是有風險的)。我會更新我的答案。 – 2009-08-23 10:06:01

1

戈茲貝達指出事情開始多早去錯了。

初學者容易犯錯誤,但即使是退伍軍人也犯同樣的錯誤。出於這個原因,退伍軍人已經做出了很好的方案來自動發現問題:

免費程序包括lint,它會在運行之前檢查代碼,以及 - 更好 - valgrind在運行時檢查代碼!在Windows上,還有其他商業替代品,如Purify

通過valgrind和靜態代碼檢查器在開發過程中運行程序,並編譯所有來自編譯器的警告,即使是經驗豐富的老兵也是開發衛生的一部分。