2011-03-14 190 views
3

緩衝區和棧有什麼區別?緩衝區溢出和堆棧溢出是一回事嗎?棧vs緩衝區

謝謝。

回答

8

堆棧溢出通常是由不受限制的遞歸引起的(儘管如果您沒有足夠的堆棧空間用於正常級別的函數調用(如嵌入式系統),甚至可能導致正常的事件發生如果限制太高,則限制遞歸)。下面的例子:

void f (void) { 
    f(); 
} 
int main (void) { 
    f(); 
    return 0; 
} 

在該例子中,函數f()非常愚蠢調用自身,並在每次這樣做,它分配一個堆棧幀,這將最終導致堆棧溢出的時間。

另一方面,緩衝區溢出是由超出緩衝區末尾的寫入引起的。他們經常感到困惑,因爲堆棧上的緩衝區溢出通常會破壞堆棧,但從技術上講,它們是非常不同的東西。基於堆棧的緩衝區溢出的一個例子是:

void f (void) { 
    char str[10]; 
    strcpy (str, "This is far too long to fit"); 
} 

這將可能損壞堆棧,因爲你想推一個27個字符的字符串(28個字節)到這是在大小隻有10字節的空間。

但是,緩衝區溢出不一定必須在堆棧上。如果緩衝區被從堆中分配(比如,與malloc),有一個很好的機會,它將垃圾內存競技場而是按:

void f (void) { 
    char *blk = malloc (10); 
    if (blk != 0) { 
     memset (blk, ' ', 100); 
     free (blk); 
    } 
} 

,除了緩衝區溢出前面的例子類似的未破壞疊加。而是寫在堆的緩衝區之外。

2

當您沒有檢查緩衝區的長度或將未終止的緩衝區傳遞給期望有一個(特別是C)的函數時,發生緩衝區溢出。你越過分配緩衝區的末尾。

緩衝區溢出:

char *foo = malloc(10); /* 10 bytes in our buffer */ 
char bar[] = "This is way bigger than 10 bytes"; 
strcpy(foo, bar); 

堆棧溢出是當您使用了所有的堆棧存儲器。這是通過遞歸調用的,在堆棧中分配太多的東西。

堆棧溢出:

int foo() 
{ 
    int bar = 4; 
    foo(); 
    return 1; /* we never get here, silly */ 
}