簡體   English   中英

C++ 標准對堆棧溢出有何規定?

[英]What does the C++ standard say about stack overflow?

我查看了 C++0x 標准草案,據我所知,那里沒有任何關於堆棧溢出的內容。 搜索“堆棧溢出”沒有結果,搜索“堆棧”我只得到了對堆棧展開和 std::stack 的引用。 這是否意味着不能有符合 C++ 標准的實現,因為當 memory 被本地 object 耗盡時,沒有允許處理錯誤的機制?

這個問題的答案表明,至少 C 標准沒有提到堆棧溢出。

為了使問題具體化,請考慮這個程序

// Program A
int identity(int a) {
  if (a == 0)
    return 0;
  char hugeArray[1024 * 1024 * 1024]; // 1 GB
  return identity(a - 1) + 1;
}
int main() {
  return f(1024 * 1024 * 1024);
}

和這個程序

// program B
int main() {
  return 1024 * 1024 * 1024;
}

我認為 C++ 標准不允許任何 C++ 實現在這兩個程序上做一些明顯不同的事情。 實際上,程序 A 不會在任何現代機器上運行,因為它在堆棧上分配了 EB 的 memory(想象一下 function 實際上使用了巨大的數組,因此編譯器無法靜默地將其刪除而不會產生不良影響)。 C++ 標准是否允許程序 A 失敗?

編輯:問題不在於標准是否應該定義堆棧溢出時會發生什么,問題是它說了什么,如果有的話。

我不確定這是否是您要查找的內容,但在 C++03 ISO 標准的附錄 B 中有以下通知:

  1. 由於計算機是有限的,C++ 實現不可避免地受限於它們可以成功處理的程序的大小。 每個實施都應在已知的情況下記錄這些限制。 本文檔可能會引用存在的固定限制,例如如何將可變限制計算為可用資源的 function ,或者說固定限制不存在或未知。
  2. 這些限制可能會限制包括以下描述的數量或其他數量。

(我的重點)我認為這意味着編譯器允許其中一個函數在另一個函數失敗時工作是完全合法的,只要編譯器說明存在哪些限制以及如何從系統可用的資源中計算它們.

行為未定義,因為標准沒有定義超出資源限制的程序會發生什么。 請注意,規范的附錄 B 中有推薦的限制。 盡管該附件是非規范性的,但實施可以忽略該附件,包括具有與此處指定不同的限制。 在 1.4 [intro.compliance] 中,規范說

如果程序不違反本國際標准中的規則,則符合要求的實現應在其資源限制內接受並正確執行該程序。

沒有什么可以說明不違反 IS 規則但不能在實現的資源限制內被接受和正確執行的程序會發生什么。 因此,對於這種情況,行為是未定義的。

堆棧溢出正在破壞操作系統已有的保護機制。 它不是該語言的特性,因為所有機器可執行代碼都將具有相同的保護。

如果你想捕捉這個特定的錯誤,你需要編寫操作系統特定的代碼。 例如,在 Linux 上,您需要捕獲 SIGSEGV(分段錯誤)信號。 但是,請注意,這也可能由 NULL 指針引用或任何其他 memory 保護問題引起,而不僅僅是堆棧溢出。

不確定 Windows、OSX 或移動設備。

堆棧溢出時發生的情況非常依賴於系統(CPU 和操作系統,有時還有編譯器,因為由編譯器插入堆棧探測器和其他安全擴展堆棧的機制),因此不可能強制執行特定響應; 如果目標平台允許,最好的辦法是提出更可取的回應。 大多數沒有; 雖然有一種合理的方法來處理堆溢出,但堆棧溢出處理程序 (a) 可能會在堆棧位於不一致的 state 中時被調用,並且上面有部分構造的堆棧幀,並且 (b) 可能涉及調用一個處理程序......它需要用於中斷幀的堆棧空間。 POSIX 指定了sigaltstack()機制,但它也有限制,並且 ANSI C C/C++ 不能合理地依賴於 POSIX 合規性。

暫無
暫無

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

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