內存篇之棧溢出

    “溢出”這個詞很生動,水滿則溢,前面說過棧就象一個容器,容器裝滿了,還要往裏裝東西,當然就會溢出了。

    有兩種不同情景都被稱爲棧溢出,一種是棧中的數據被越界覆蓋,wiki中稱這種情況爲stack buffer overflow。一種常用的黑客攻擊手段--棧溢出攻擊,就是通過棧越界訪問,用事先設計好的數據覆蓋正常棧裏的內容。比如把保存函數返回地址的棧內存用某段黑客代碼的地址覆蓋,函數結束時不能正確返回,而是順着被篡改的地址跳到黑客代碼處,攻擊者從而獲得系統控制權,執行一些非法操作。這屬於一種有意識的越界訪問,但並沒有真正溢出棧的存儲空間的邊界,只是破壞了棧內的數據。

    而嵌入式軟件需要注意另一種真正的棧溢出:所有棧空間都被填滿,即真正的stack overflow。因爲棧空間說到底就是一塊固定大小的內存,當程序不斷壓棧,以至超出了系統預留的棧空間,壓棧操作就可能越界覆蓋其它內存功能模塊,這就是真的棧溢出。

    棧溢出或者說佔用過多主要有幾種原因:

a. 遞歸函數調用

    函數調用過程需要保存當前地址,傳入的參數等,遞歸函數不斷調用自身,直到某條件滿足,是非常消耗棧的一種方式,因此嵌入式系統中一般不使用遞歸函數。

b. 過大的局部變量

    嵌入式平臺下棧的大小有限,所以大的緩存應儘量分配到堆內存,避免大尺寸的局部數組。可以對照Wiki的解釋(簡化):

Stack overflow mean:

    Stack overflow, when too much memory is used on the call stack

    Stack buffer overflow, when a program writes to a memory address on the program's call stack outside of the intended data structure, usually a fixed length buffer.

A stack overflow occurs when too muchmemory is used on the call stack. The call stack contains a limited amount of memory. The size of the call stack depends on many factors, including the programming language, machine architecture, multi-threading, and amount of available memory. When too much memory is used on the call stack the stack is said to overflowThis is usually caused by one of two types of programming errors.

    a. Infinite recursion

    The most common cause of stack overflows is excessively deep or infinite recursion.

     An example of infinite recursion inC language:  main() {   main(); } .The main function calls itself until the stack overflows resulting in a segmentation fault.

    b. Very large stack variables

    The other major cause of a stack overflow results from an attempt to allocate more memory on the stack than will fit. This is usually the result of creating local array variables that are far too large. For this reason arrays larger than a few kilobytes should be allocated dynamically instead of as a local variable.

    Stack overflows are made worse by anything that reduces the effective stack size of a given program. For example, the same program being run without multiple threads might work fine, but as soon as multi-threading is enabled the program will crash. This is because most programs with threads have less stack space per thread than a program with no threading support.

    程序移植過程中兩種情況容易發生真正的棧溢出:1)windows上運行正常的程序,移植到嵌入式平臺後發生奇怪錯誤:如跟蹤某函數體內的return結果明明爲0,但返回上一層函數後就突然變成另外的值,這多數就是由於大數組導致了棧溢出。2)程序從單線程移植到多線程環境,容易棧溢出,因爲多線程往往對棧空間限制得更嚴格,這裏涉及另一對概念,系統棧與任務棧,後文再續。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章