2011-03-14 150 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 */ 
}