2. 檢測堆棧溢出,并采取改進措施。
觀察堆棧深度的方法很簡單:
* 向整個內存堆棧區寫入一個特定的數據圖案符號,如55AA。
* 在預期使用最大堆?臻g的條件下運行系統。
* 使用仿真器或其它工具檢查堆棧存儲區,看有多少符號圖案由于堆棧的使用而被改寫了。
當然,這些步驟并不能保證在一些不同條件下不會需要更多的堆棧,但確實可以表明所需要的最小堆棧數。
使用帶內存管理單元(MMU)的處理器時,有可能檢測出運行時的堆棧溢出現象。MMU將內存劃分為多個區域,用一個受保護的內存段來“警戒”堆棧區域。發生堆棧溢出時,處理器將訪問這個受保護段。這個操作將引發一個異常事件(如產生SIGSEGV信號),可被程序捕獲到。創建線程時,與實時POSIX標準兼容的RTOS提供有這種堆棧警戒功能選項,大大簡化了編程人員的工作。GNU工具等其它開發環境包含有編譯器開關,可在程序中添加實現堆棧警戒功能所需的代碼,但它們仍然依靠底層操作系統來有效地處理堆棧溢出。但是,按照這種方式檢測溢出還只是問題的一部分。為了使這類設計更為有效,系統必須能夠從堆棧溢出中恢復過來并繼續正確地工作。
在一個對安全或任務要求嚴格的應用中,系統運行時在測試或檢測堆棧溢出期間監視堆棧的深度可能并不是一項足夠的風險控制措施。對于一些應用,必須確保系統絕對不會越出所分配的堆棧范圍;只有通過完整的堆棧深度分析才能證明這一點。這意味著,如果整個程序在同一內存空間運行,則必須對所有代碼執行這項分析。不過,如果使用MMU,分析?珊喕。在設計系統時,可將所有關鍵代碼置于一個或多個獨立線程內,而這些線程分別在各自的保護內存段中運行。這樣,只要對這些關鍵線程進行堆棧使用分析就可以了。當然,這項簡化設計假定當非關鍵線程溢出其堆棧并失效時,關鍵線程仍可正確執行。
由于分析工作所需的堆棧使用數據來自匯編語言清單,因此修改代碼時,相應模塊的堆棧使用信息必須予以更新。如果使用不同的編譯器版本,或者改變了優化設置,也必須復核整個分析過程。在理想情況下,編譯器將提供每個函數(如果不是每個線程的話)的堆棧使用數量,因為它擁有計算需要的所有信息。例如,瑞薩公司提供有Call Walker,這是該公司高性能的Embedded Workshop開發環境的一部分。這個工具可以圖形化地顯示每個函數使用的調用樹和堆棧,包括運行時庫和C庫的函數。Call Walker也能找出使用堆棧數量最大的路徑。使用這樣的工具可以實現步驟1到步驟3的自動化。
延伸閱讀
文章來源于領測軟件測試網 http://www.kjueaiud.com/