2011-05-28 143 views
3

有沒有辦法糾正失敗的靜態分配或程序運行時只是通過分段或總線故障失敗?感謝:檢查堆棧分配是否失敗?

帖子是由C99如何讓瘋狂的東西就像char text[n];

編輯啓發。我現在明白粗體的部分不是靜態分配。所以只是爲了檢查,如果像char text[1234];失敗,可能的恢復策略是相同的?

+1

這不是靜態分配。這是在堆棧上。如果你認爲它可能會失敗,那麼使用堆。 – 2011-05-28 21:01:55

+0

這不是靜態分配。 – 2011-05-28 21:02:58

+0

用'反引號'代碼,而不是**雙星號**。 – 2011-05-28 21:33:47

回答

1

您或許可以捕捉到信號,但您可以做的其他事情不多。當然,在使用它之前檢查n以確保它具有合理的價值可以立即解決這個問題。

+0

信號,好主意...... – ImJustALittleCatfish 2011-05-28 20:57:33

+3

@ImJustALittleCatfish **危險,威爾羅賓遜!**請不要相信信號是一個好主意。信號總是一個壞主意(整本書可以寫出信號和異步信號不安全如何使編程複雜化)。 – cnicutar 2011-05-28 20:59:45

+0

嗯,「複雜」和「壞」之間有區別。但我可以想象爲什麼用這種方式使用信號會很麻煩。 – ImJustALittleCatfish 2011-05-28 21:06:36

3

char text[n]在堆棧上分配一個可變大小的數組。它只需要將堆棧指針遞增n

如果發生堆棧溢出,用戶空間進程可以做的事情並不多 - 這取決於操作系統向進程發送信號並終止進程或調整堆棧大小。

+1

'libsigsegv'有許多平臺的堆棧溢出處理程序。 – 2011-05-28 21:14:05

+0

@Chris:推薦更多1980年代風格的「便攜式憑藉對每個已知系統具有特定系統的黑客」的代碼... ;-) – 2011-05-28 22:15:23

+0

@R .. - 我沒有說它是好的,只是它可能是相關的。出於這個原因,我不會首先使用VLA。 – 2011-05-28 23:42:35

1

永遠不要檢查你不知道如何處理的錯誤情況。

說真的,你打算做什麼?只有一小部分函數可以從信號處理程序中調用(請參閱man 7 signal),而printf和longjmp(longjmp是我能想到從這種問題中恢復的唯一方式)不是其中的一個。如果你想要重新執行這個過程,你可能會有一個保姆來完成這項工作,並避免混亂。

注意根據man alloca你實際上並沒有被告知「分配」失敗,當你嘗試訪問壞內存時,你只是得到一個SIGSEGV,當然這可能不會發生在文本[]數組中所有的,或者甚至沒有在分配文本[]的函數中。

雖然以上兩段是基於Linux的,但總體理論對於所有平臺都是正確的。

使用malloc並有乾淨的處理。理智吧。

[編輯]

其實有嘗試做到這一點的一種方式,那就是通過計算堆棧的開始(在主記錄疊層)和堆棧限制(希望操作系統不會用完頁)。然後在你做大堆棧分配之前,你可以計算你到底有多近。給你一個慷慨的擺動室,並在你分配之前失敗。

+1

只要您可以確保在調用信號處理程序時沒有運行異步信號不安全的函數,則來自信號處理程序*的'longjmp'是有效的。確切地說,是 – 2011-05-28 22:14:15

+0

@R。但是,你很少能知道這一點。任何SIGSEGV出於任何原因都會導致該問題。但讓我們假設完美的編程,並且在大量分配之前沒有功能會導致問題。你必須確保函數中的大分配*和它調用的任何函數都不會調用不安全的函數。雖然實際上完美的程序員文本讓我覺得這應該作爲犯罪前處理。更新了答案。 – 2011-05-28 22:39:27

0

這是一個堆棧分配而不是靜態。失敗模式是堆棧溢出。堆棧溢出的最合理策略是將其視爲終端。

設計你的代碼,使它不會溢出堆棧,而不是試圖使它適應堆棧溢出。