C程序中堆栈破坏的典型示例

时间:2010-10-06 18:58:31

标签: c memory-management stack

有人可以教我一个常见的例子,其中(!)你在C程序中销毁堆栈?我在Ubuntu中使用GCC。 感谢。

4 个答案:

答案 0 :(得分:5)

这取决于“破坏堆栈”的含义,但这是一个常见的错误,通常会导致重要的堆栈驻留数据损坏:

void dumb()
{
    char small[2];
    strcpy(small, "too long to fit"); // Writes past the end of "small", overwriting vital information
}

这是安全漏洞的常见来源。它可能用于劫持指令指针,使恶意代码能够执行。请参阅buffer overflow

可能被描述为“破坏堆栈”的另一个错误是infinite recursion的情况(在该页面上向下滚动):

int add(int n)
{
    return n + add(n + 1);
}

由于缺少退出条件,因此会将如此多的帧推入堆栈,最终会“满”。 (除非编译器可以应用tail-call optimization;见下文)

这两个示例的编译没有使用GCC 4.4.3的警告。


注意:正如Billy ONeal在下面指出的那样,这些示例的行为特定于x86,而不是C作为语言,并且可能因编译器而异。这并不是说他们演示如何在C的特定(并且非常常见)实现中打破堆栈。

答案 1 :(得分:2)

以下是一些堆栈可能被破坏的示例。

char* foo()
{
    char str[256];
    return str;
}

void bar()
{
    char* str = foo();
    strcpy(str, "Holy sweet Moses! I blew my stack!!");
}

或者,

void foo()
{
    char* str; // uninitialized; has garbage value
    strcpy(str, "Holy sweet Moses! I blew my stack!!");
    // well, could be anything you are trashing
}

void foo()
{
    int* ptr; // uninitialized; has garbage value
    *ptr = "0xDEADBEEF";
    // well, could be anything you are trashing
}

答案 2 :(得分:0)

至少,你不能不符合C标准。您可以使用GCC的内联汇编程序功能来处理堆栈指针。

编辑:我想调用exitabort terminate (终止只在C ++中)会导致堆栈被破坏:P < / p>

答案 3 :(得分:0)

我不确定你的意思,但每当你退出一个函数时,该函数的“堆栈”就会被破坏。例如:

void foo(void) {
    // a, b and c are "allocated" on the stack here
    int a, b, c;

}    // a, b and c are destroyed here

实际上,堆栈永远不会以您可能想到的方式被破坏。有一个指向堆栈顶部的指针,并且函数引用相对于当前堆栈顶部的位置。当函数退出TOS指针时会减少一定量,但不会发生实际的破坏。因此理论上你可以在退出后仍然访问函数中的值,尽管这不是一个好主意。

您可能需要查看以下内容:

How Does The Function Call Stack Work?

Calling Conventions in C and C++