问题非常明显,所以我只会告诉你一些代码:)
#include <stdio.h>
#include <string.h>
char *test1()
{
static char c;
char *p;
p = &c;
printf("p[%08x] : %s\n", (unsigned int)p, p);
return p;
}
void *test2()
{
static char i;
char *buf;
int counter = 0;
for(buf = (char *)&i ; ;counter += 8)
{
memset(buf + counter, 0xff, 8);
printf("write %d bytes to static area!\n", counter);
}
}
int main()
{
char *p;
p = test1();
strcpy(p, "lol i asd");
p = test1();
strcpy(p, "sunus again!");
p = test1();
strcpy(p, "sunus again! i am hacking this!!asdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
p = test1();
test2();
return 0;
}
首先我写了test1()
。
如您所见,那些strcpy
应该导致段错误,因为它显然访问了非法的内存区域。我知道一些关于静态变量的基本知识,但这对我来说很奇怪。
然后我写了test2()
。
最后,它导致了一个段错误,在之后它写了差不多4k字节。
所以,我想知道如何避免这种错误(静态变量溢出)的发生?
为什么我可以访问那些静态内存区域? 我知道他们不在堆栈中,也不在堆中。
PS。也许我没有清楚地描述我的问题。 我有几年的C编程经验;我知道当这不是静态的时候会发生什么。 现在静态几乎改变了一切,我想知道为什么。
答案 0 :(得分:1)
未定义的行为只是 - undefined 。它可能看起来像是在工作,它可能会崩溃,它可能会偷走你的午餐钱。只是不要这样做。
答案 1 :(得分:1)
当你超过4kB的内存页面时会发生分段错误,所以幸运的是你可以在它发生之前写完4k,如果已经使用了下一页 - 即使这是不能保证的。 Gcc的堆栈保护器有时会有所帮助,但在这种情况下却不行。 Valgrind也可以提供帮助。这些都不是保证。你最好自己照顾它。
答案 2 :(得分:0)
您无法避免覆盖未在C中分配的内存。
关于失败的方式......应用程序崩溃或行为不当的时间,地点和方式完全取决于编译器,编译器标志和随机状态存储器在程序开始执行之前。您正在访问您不应该访问的内存,并且在C中完全未定义访问将对操作环境产生什么影响。
管理内存的语言(例如Java,C#)可以帮助您,但当然边界检查需要付出代价。
您当然可以使用内存管理库(malloc / free / new / delete的替代品)来尝试检测不正确的内存管理。
答案 3 :(得分:0)
您可以通过了解您的记忆区域有多大以及不在这些区域的边界外书写来避免这个问题。没有其他可靠的方法可以解决这个问题。