堆疊溢位

-{zh-hans:堆栈溢出; zh-hant:堆疊溢位}-（）在電腦科學中是指使用過多的記憶體时導致呼叫堆疊產生的溢位，也是缓冲区溢出中的一種。堆疊溢位的產生是由於過多的函數呼叫，導致使用的呼叫堆疊大小超過事先規畫的大小，覆蓋其他記憶體內的資料，一般在遞迴中產生。堆疊溢位很可能由無限遞迴（Infinite recursion）產生，但也可能僅僅是過多的堆疊層級。

堆疊溢位在核心設計中尤其危險，因此很多入門核心設計教程建議使用者不要嘗試使用遞迴程式；而是基於安全和效能考量，改用迴圈處理問題。

在POSIX相容平台上，堆疊溢位通常會造成作業系統產生SIGSEGV訊號。

遞迴溢位
無限遞迴
無限遞迴是堆疊溢位的最常見原因，如以下的C/C++語言程式會產生堆疊溢位：
int foo()
{
    return foo();  //這裡出現无限重复的自我调用
}

然而有些語言（如Scheme）支援尾端遞迴優化，在這些語言中只有一般遞迴會產生堆疊溢位，而尾端遞迴不會：
(define (foo) (foo))
(define (foo) (+ (foo) 1))

这段代码中，前者（第一句）进入無窮迴圈（Infinite loop），但不会产生堆疊溢位；后者（第二句）则会产生堆疊溢位。

防止堆疊溢位
多數無限遞迴出現原因，都是基於程式本身沒有錯誤檢測機制：
int factorial( const int *const n ){
    if ( *n == 0 )
        return 1;
    else
        return *n * factorial( *n-- );  //這裡出現自我呼叫
};
如果在這裡的n是負數則會出現無限遞迴。其實，這段程式可以簡單地加以修改，把n的型別由整數改為非負整數即可解決：
unsigned int factorial( const unsigned int *const n ){
    if ( *n == 0 )
        return 1;
    else
        return *n * factorial( *n-- );
};
或者使用迴圈處理：
unsigned int factorial( const unsigned int *const n ){
    unsigned int i, result;
    for ( i = *n, result = 1; i > 0 ; --i )
        result *= i;
  //自我呼叫部份改為迴圈處理
    return result;
};

参看
溢位
缓冲区溢出
呼叫堆疊
棧緩衝區溢出

註釋

Category:计算机编程
Category:程式錯誤