有人可以教我一个常见的例子,其中(!)你在C程序中销毁堆栈?我在Ubuntu中使用GCC。 感谢。
答案 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的内联汇编程序功能来处理堆栈指针。
编辑:我想调用exit
,abort
或 (终止只在C ++中)会导致堆栈被破坏:P < / p>
terminate
答案 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指针时会减少一定量,但不会发生实际的破坏。因此理论上你可以在退出后仍然访问函数中的值,尽管这不是一个好主意。
您可能需要查看以下内容: