关于指针:为什么局部变量销毁后,p的值还是不变啊??

weixin_42688840 2018-07-13 06:44:02
为什么局部变量销毁后,p的值还是不变啊??
两次printf结果,第一次与*f()函数中的b值相同,第二次为随机值;
求解释!!
代码如下:
#include <stdio.h>

int *f()
{
int b = 0xcafe9abe;
int *p1 = &b;
return p1;
}

void g()
{
int b = 0xdeadbeee;
}

int main()
{
int *p = f();
printf("%X\n", *p);
//g();
printf("%X\n", *p);
}

...全文
878 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
Jacky_Lu 2018-08-22
  • 打赏
  • 举报
回复
你再运行一个新的函数 里面的数据就会变化了
临时变量是在堆栈里面的,
你退出了一个函数 堆栈往前移动,
你进入一个函数 堆栈往后移动
AlbertS 2018-08-06
  • 打赏
  • 举报
回复
还没有人覆盖这个内存的内容,但是允许其他人覆盖,所以不建议这样写
赵4老师 2018-08-06
  • 打赏
  • 举报
回复
所以stack攻击才得以成立。
MUKE_FIGHTING 2018-08-06
  • 打赏
  • 举报
回复
调用f()函数时,开辟了个临时int空间(设该空间地址为1234),存放b的值并吧b的地址给了p;
当执行第一个printf语句时,存放在(空间1234)里的值还没被重置,
当执行完第一个printf语句后,空间(1234)里的值就被重置了
所以第二个printf语句输出0;
调用完f()后,函数里面的变量b是被销毁了的,但存放b的值的地址空间是没办法销毁的
不过里面的值会在执行一个语句后刷新重置;
如果b是全局变量,调用f()后就不会被销毁,存放b的值的地址空间的值也就不会刷新,多少次printf值都不会变
以上是我个人理解
赵4老师 2018-08-03
  • 打赏
  • 举报
回复
栈中的变量通常包括函数参数和函数里声明的临时变量。
栈中的基本变量退出其作用域时,没有谁执行一段代码去释放/销毁/析构它所占用的内存,仅仅是没人再去理会的留在当前栈顶上方的若干遗留下来可被后续压栈操作覆盖的无用数据而已。
而栈中的类变量退出其作用域时,会自动执行其析构函数,……
赵4老师 2018-08-03
  • 打赏
  • 举报
回复
栈中的变量通常包括函数参数和函数里声明的临时变量。
栈中的基本变量退出其作用域时,[color=#FF00FF]没有谁执行一段代码去释放/销毁/析构它所占用的内存,仅仅是没人再去理会的留在当前栈顶上方的若干遗留下来可被后续压栈操作覆盖的无用数据而已。[/color]
而栈中的类变量退出其作用域时,会自动执行其析构函数,……
eziowayne 2018-08-02
  • 打赏
  • 举报
回复
因为被调函数进行了压栈的操作,当返回时,尽管函数栈被销毁,但实际上只是栈顶的指向被修改了而已,这块内存实际上还是可以被访问的。如果这时候你再去调另外一个函数,这个值可能就发生变化了,你可以试验一下。
  • 打赏
  • 举报
回复
3楼说的有理,讨论这个没有多大的意义,关键是你要理解指针是怎么回事 另外在f()里面,这样用是不妥的,返回了一个局部变量的一个地址,这个地址实际上出了函数就不要用了才是
斯文的野蛮人 2018-08-02
  • 打赏
  • 举报
回复
p的值是地址,释放的是存在这个地址里的内容,但是这个地址本身是不变的。
孑澈 2018-07-30
  • 打赏
  • 举报
回复
那块内存没有被其他程序使用,所以值没有被修改
赵4老师 2018-07-26
  • 打赏
  • 举报
回复
栈中的变量通常包括函数参数和函数里声明的临时变量。
栈中的基本变量退出其作用域时,没有谁执行一段代码去释放/销毁/析构它所占用的内存,仅仅是没人再去理会的留在当前栈顶上方的若干遗留下来可被后续压栈操作覆盖的无用数据而已。
而栈中的类变量退出其作用域时,会自动执行其析构函数,……
Dobzhansky 2018-07-24
  • 打赏
  • 举报
回复
说的都很好
赵4老师 2018-07-24
  • 打赏
  • 举报
回复
其实电脑开机后物理内存的每个字节中都有值且都是可读写的,从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页,一页通常为4KB。
文虫并雕 2018-07-23
  • 打赏
  • 举报
回复
先把堆栈和指针理解了,在看,你的问题自己就解决了。

#include <stdio.h>

int *f() // normal func return type int*
{
int b = 0xcafe9abe; //int value b = 0xcafe9abe;
int *p1 = &b; // p1 is a point value = b 's address;
return p1; // return value is a int * point value = b's address (一旦函数结束,int b 的地址(栈)已经被操作系统释放)
}

void g()
{
int b = 0xdeadbeee;
}

int main()
{
int *p = f();
printf("%X\n", *p);
//g();
printf("%X\n", *p);
}


不是俩个函数的局部变量名字一样就在内存里一样。仔细看书吧。
OnePeace888 2018-07-22
  • 打赏
  • 举报
回复
都说的很好111
赵4老师 2018-07-22
  • 打赏
  • 举报
回复
理解讨论之前请先学会如何观察

http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素
自信男孩 2018-07-17
  • 打赏
  • 举报
回复
之所以一样,是因为f函数使用的空间未被其他函数占用。局部变量在函数调用结束后是会被自动释放,自动释放的意思就是这部分栈空间可以被其他的函数栈使用,如果继续读取已经释放的栈空间是未定义行为。
如果已经释放的栈空间被别的函数栈使用,那么b的内存空间可能被写入新的值。因此输出的就不是原来的值了。
636f6c696e 2018-07-16
  • 打赏
  • 举报
回复
函数返回后,函数里局部变量的内存空间回归操作系统,因此里面的内容不可预期。
在你的例子中,如果这段内存空间操作系统还没有写入,内容不变;操作系统写入了,内容就有变化。
对于开发者而言,只需记住:函数返回局部变量是不可取的。
跑不了的你 2018-07-15
  • 打赏
  • 举报
回复
就是你刚写过,虽然你放弃了他 但是你放弃的是访问他的权力,他还是那样没有变 直到有人在此访问他改变他的值啊
vnvlyp 2018-07-14
  • 打赏
  • 举报
回复
使用已经销毁的指针是未定义行为,讨论这个毫无意义
要想知道为什么第一次可以第二次不行请自行单步汇编去理解,简单地说就是第一次堆栈的值并没有被覆盖,第二次因为之前调用了一次printf,堆栈已经被覆盖了
加载更多回复(3)

69,373

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧