目录
- 1. 删掉 printf 代码就崩溃了
- 2. 运行代码为什么报错
- 2.1 为什么程序报错 Segmentation fault ?
- 2.2 为什么程序每次都稳定的报错?
- 2.3 研究一下两个局部变量的值和地址?
- 3. 为什么加一个 “\n”就可以正确执行?疑问??
今天读到一篇有意思的文章【就删了个printf,代码崩了】,是关于栈内存溢出问题的,阅读有感,记录如下。
1. 删掉 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;
}
2. 运行代码为什么报错
2.1 为什么程序报错 Segmentation fault ?
2.2 为什么程序每次都稳定的报错?
2.3 研究一下两个局部变量的值和地址?
原因分析:
✅ 为什么程序报错 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
3. 为什么加一个 “\n”就可以正确执行?疑问??
这个问题我还没搞明白,有了解的大神欢迎留言。