簡體   English   中英

C ++中的隨機段錯誤

[英]Random segfaults in C++

我是C ++的新手,我不知道從哪里開始,所以我將代碼上傳到了pastebin,因為其中有很多。

即使使用gcc的-Wall選項,此代碼也可以正常編譯,並且不會發出警告。

它應該生成所有素數,直到一個命令行參數給定的數字。

對於較小的數字(例如4,000或5,000),它可以正常工作。 在較大的數字(例如4,000,000)上,它幾乎總是在出現段錯誤的情況下崩潰。 在介於兩者之間的數字上,是否運行會受到打擊。

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 []素數; 在代碼末尾(當素數數組完成時)

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

嘗試使用new / delete分配數組。

一方面,這是有問題的:

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

這是從給定數組的開頭開始的。 當內存塊中int大小的值不為零時,移至下一個內存塊。 這里發生的事情是它將繼續超出數組的末尾,最終使內存不應該混亂,這是導致段錯誤的原因。 似乎隨機的原因是,有時數組末尾的內存為空,這可以正常工作。 但是有時不是,然后訪問不應該訪問的內存並崩潰。

那可能不是唯一的問題,但這是我注意到的第一個問題。 要修復此問題,請跟蹤數組的大小,將其傳遞給函數,然后使用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: :向量。 這是一個可擴展的數組,可以讓您在找到數組時將素數添加到數組中,而不是分配不必要的整噸空間。

您應該動態分配素primes數組primes ,即:

int* primes = new int[max];

您的程序甚至不應按原樣編譯。 祝您作業愉快!

其他人(例如Goz)提供了正確的答案-未初始化變量的值因運行而異,因此無法依賴。 正如其他人指出的那樣,在堆棧上分配大型數組也是有風險的,因為堆棧空間通常比堆空間更稀缺。

附帶的問題是,以與primes[max]的方式分配可變大小的數組不是符合標准的C ++,而是g ++擴展,因此,您現有的代碼不太可能與其他編譯器一起使用。 您可以改用newdelete ,但是在這些情況下最好養成使用vector<int>的習慣,因為它將為您進行清理。

[編輯:感謝威爾指出問題的真正根源在其他地方。]

戈茲指出了早期的事情是怎么開始出錯的。

初學者容易犯錯誤,但即使是退伍軍人也會犯完全相同的錯誤。 因此,退伍軍人制定了出色的程序來自動發現問題:

免費程序包括lintvalgrind ,后者在運行代碼之前對其進行檢查,而lint可以在運行之前對其進行檢查! 在Windows上,還有其他商業替代產品,例如Purify

即使是經驗豐富的老手,通過valgrind和靜態代碼檢查器在開發過程中運行程序以及使用編譯器啟用的所有警告進行編譯也是開發過程中的一部分。

int primes[max];

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM