今天读到一篇有意思的文章【就删了个printf,代码崩了】,是关于栈内存溢出问题的,阅读有感,记录如下。
就是以下这句代码,删掉就崩溃了 留着代码就正常执行
void fool(){
int arry[10];
memset(arry,1,sizeof(arry));
//printf("%s","hello world! \n"); //*****就是这句代码,删掉就崩溃了 留着代码就正常执行
}
void bar(){
int idx;
char *buf = (char *)malloc(1);
buf[idx] = 'A';
}
int main(){
fool();
bar();
return 0;
}
原因分析:
✅ 为什么程序报错 Segmentation fault ?
bar()函数中,局部变量 idx 未初始化,未初始化的变量是一个随机值,所以 当*buf只分配了1字节空间时,buf[idx] 赋值,明显是内存访问异常了
✅ 为什么程序每次都稳定的报错?
按照问题1 的解答,idx 若果是个随机数,那么就有概率随机数是一个比较小的数,比如0和1,就会有小概率的时候不报错,但是事实上是运行 1000次也会报错1000次,这是为什么?
通过设置断点调试发现,idx 可不是个随机数,而是每次都有一个固定的值,如下图所示
固定值 16843009 可不是一个随机数,它的16进制为 0x01010101,这下明白了吧?idx的值和 fool() 函数中的 arry[0] 的值一致,恰巧这两个都是 局部变量,我们进一步研究

✅ 研究一下两个局部变量的值和地址
通过打印信息看出,这两个局部变量的地址竟然一样,因此 idx这个局部变量刚好是申请在了上次刚刚用完的栈空间

解释如下:
fool() 函数时,在栈上申请了 40 字节空间,并给每个地址赋值 0x01010101 ,执行完 fool() 函数,栈空间释放bar() 函数时,栈指针在上次的位置,继续申请空间,还是在 地址20的位置,由于 idx 变量未初始化,因此还是上次残留的值,也就是 0x01010101
这个问题我还没搞明白,有了解的大神欢迎留言。

