簡體   English   中英

C99如何處理無法在運行時創建可變長度數組的情況?

[英]How does C99 handle being unable to create a variable length array at run time?

我對嵌入式系統進行編程。 一個黃金法則是我們永遠不要調用malloc() 所有數據必須在編譯時靜態分配。

因此,我對C99引入的可變長度數組不是很熟悉。

這個概念似乎很清楚,我不需要解釋。 我的問題是,如果沒有足夠的可用內存用於這種陣列,在運行時會發生什么?

我可以想像,它與o / s有關,也許與編譯器有關,與GCC / Linux和Windows上的MS visual Studio C有關? 是否有X99或Posix定義?

從標准的角度來看,嘗試以實現無法容納的大小分配VLA會調用未定義行為。 因為標准沒有提供發現實現可以安全創建的大小數組的方法,並且沒有強制實現允許任何特定大小,所以創建大小大於1的VLA對象的任何嘗試都應視為調用未定義行為,除非碰巧對實現的內部工作了解得足夠多的情況,以確定它可以處理的VLA的大小。

如果malloc()不可用,最好的選擇是定義一個具有最大對齊要求的任何類型的大型數組,將其地址存儲到一個volatile限定的指針中[該指針本身所在的存儲空間應該因此被限定]讀取然后將其解釋為內存池的開始。 原始數組對象不能有任何其他用途。 盡管標准不能保證編譯器不會決定是否應生成代碼來檢查指針是否仍標識原始對象,如果可以,則跳過使用該指針訪問除原始對象以外的任何代碼的代碼。對象的類型,在指針上使用volatile應該確實不太可能。

創建內存池后,您可以編寫自己的內存管理函數以使用它,盡管任何時候將指針返回到池中,可能有必要使用volatile -pointer-laundering hack來防止編譯器使用type-基於別名的處理可以證明將存儲的最后使用作為舊類型視為相對於未使用的新類型。

可變長度數組通常在堆棧上分配。 像在堆棧上分配的任何其他變量一樣,這通常是通過從堆棧指針中減去(或為向上增長的堆棧添加)來完成的。 可能會使用幀指針,以便在動態確定對堆棧指針的更改時,函數可以跟蹤其堆棧幀。 與其他堆棧分配一樣,此過程中通常不進行錯誤檢查。

這帶來了一些危險。

  1. 分配給堆棧的空間可能溢出。 根據平台的不同,這可能導致內核出現某種內存錯誤,可能導致平台動態分配更多的堆棧空間,或者可能導致其他內存的覆蓋。
  2. 在使用超出堆棧保護頁面的平台進行自動堆棧增長和/或檢測堆棧溢出的平台上,足夠大的堆棧分配可能會“跳過”這些頁面。 如果通常會捕獲堆棧溢出,則可能導致內存保護錯誤或更嚴重的內存損壞。

這些風險都不是可變長度數組所特有的,但是可變長度數組使它們更有可能被隱藏,直到用特定參數調用代碼為止。

暫無
暫無

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

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