返回信息流#include<stdio.h>
int *foo()
{
int a[2];
a[0] = 1;
return a;
}
int main(void)
{
int *p;
p = foo();
printf("%d\n",*p);
}
今天突然看到以前自己写过一段这样的代码,感觉不对哇,不是函数调用完之后里面的变量就会释放么,那为啥还能打印出1啊,就好像malloc一样。。。
求大牛敲醒。。。[ema11]
这是一条镜像帖。来源:北邮人论坛 / cpp / #82775同步于 2014/9/22
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖
关于函数调用后里面的一些变量(数组)之类的释放问题
Smeagol
2014/9/22镜像同步9 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
#include <stdio.h>
int *foo()
{
int a[2];
a[0] = 1;
return a;
}
void flush () {
char a[] = "abcdefghij";
;
}
int main(int argc, const char *argv[])
{
int *p;
p = foo();
printf("%d\n",*p);
flush ();
printf ("%x\n", *p);
return 0;
}
看看打印的东西是不是变了。 而且变的有些规律。
我觉得是因为指针所指向的那块内存在之后的程序中未被使用,所以继续保存着之前的值,如果之后还有后续的代码,那么那块内存空间就会被再次利用了,值自然就会改变了。和malloc还是不一样的!
a是分配在栈上的,所谓的“局部变量自动释放”其实就是栈顶指针的不断偏移而已。
foo返回后,栈顶恢复回调用foo前的,这个时候p的地址相当于在当前栈顶之外,换句话说就是访问越界,不过执行printf的话值还是可以打出来的,又因为没有其它人再用那块内存,所以值还是1不变。
【 在 Smeagol 的大作中提到: 】
: [code=c]
: #include<stdio.h>
: int *foo()
: ...................
另外一个细节,就是在执行printf的时候,返回地址、参数等信息会再次压栈,这个时候就会把刚才“栈顶之外”的内存覆盖。巧在printf的参数*p是先取了原来a的内存值,再压栈,所以第一次printf得到的值还是1。
你可以试试连续调两次printf,第二次打出来的值就可能是个很奇怪的数了,因为第二次*p的时候,p指向的位置(即原来a所存储的位置)已经被第一次的printf压栈信息覆盖了。
【 在 hutaow 的大作中提到: 】
: a是分配在栈上的,所谓的“局部变量自动释放”其实就是栈顶指针的不断偏移而已。
: foo返回后,栈顶恢复回调用foo前的,这个时候p的地址相当于在当前栈顶之外,换句话说就是访问越界,不过执行printf的话值还是可以打出来的,又因为没有其它人再用那块内存,所以值还是1不变。
:
感觉你应该说的是对的,不过对于“巧在”,你的意思是调用printf函数时也需要压栈,正好p的值就是a的地址是么?真有那么巧?
【 在 hutaow 的大作中提到: 】
: 另外一个细节,就是在执行printf的时候,返回地址、参数等信息会再次压栈,这个时候就会把刚才“栈顶之外”的内存覆盖。巧在printf的参数*p是先取了原来a的内存值,再压栈,所以第一次printf得到的值还是1。
: 你可以试试连续调两次printf,第二次打出来的值就可能是个很奇怪的数了,因为第二次*p的时候,p指向的位置(即原来a所存储的位置)已经被第一次的printf压栈信息覆盖了。
:
最后半句的意思理解有误,调用printf时压栈会把a原本的值覆盖掉,好在调用printf前先执行了*p的动作,把即将被覆盖的a地址的值取了出来,然后再将取到的值跟着printf重新压栈。所以第一次调用的时候是可以取到a原本的值的。
这里其实也不存在巧,只是“好在”而已。
【 在 Smeagol 的大作中提到: 】
: 感觉你应该说的是对的,不过对于“巧在”,你的意思是调用printf函数时也需要压栈,正好p的值就是a的地址是么?真有那么巧?
gcc下怎么都是1呢
【 在 hutaow 的大作中提到: 】
: 最后半句的意思理解有误,调用printf时压栈会把a原本的值覆盖掉,好在调用printf前先执行了*p的动作,把即将被覆盖的a地址的值取了出来,然后再将取到的值跟着printf重新压栈。所以第一次调用的时候是可以取到a原本的值的。
: 这里其实也不存在巧,只是“好在”而已。
: