返回栈内存指针问题

camelisi 2009-12-30 08:17:25
最近没事翻了翻 林锐的<<高质量的C++编程指南>>,看到一个例子
char *GetString(void)
{
char p[] = "hello world";
return p; // 编译器将提出警告
}
void Test4(void)
{
char *str = NULL;
str = GetString(); // str 的内容是垃圾 ( 书上如是说 )
cout<< str << endl;
}


我用GC++调试了一下,编译器报警,但居然能正常输出 hello world。。。
GetString(void)里面的p不是在栈上分配的内存吗?按理说应该是返回乱码啊,不解.
各位知道的能说说为什么吗?
...全文
237 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaoxiaomayipie 2011-09-10
  • 打赏
  • 举报
回复
哇,csdn果然是高手云集的地方~菜鸟受教~
arong1234 2009-12-30
  • 打赏
  • 举报
回复
返回值本身是安全的没错,但是对于指针和引用,我们关心的不是返回值自己,而是返回值所指向的东西,那东西不是安全的
[Quote=引用 16 楼 traceless 的回复:]
1 >
返回值和栈不栈的有什么关系,返回值在栈销毁前已经保存到一个“安全”的地方
栈销毁后,这个值才向 “=”右边赋值

[/Quote]
traceless 2009-12-30
  • 打赏
  • 举报
回复
1 >
返回值和栈不栈的有什么关系,返回值在栈销毁前已经保存到一个“安全”的地方
栈销毁后,这个值才向 “=”右边赋值

2 >
char *GetString(void)
{
int b = 1;
char arr[] = "hello world";
char *p = "hello world";
int a = 2;
//以下的值分别是这四个:0012FE7C, 0012FE68, 0041FA14, 0012FE50
printf("%p, %p, %p, %p\n", &b, arr, p, &a); //可以看出arr所指向的字符串地址是在栈,p所指向的字符串地址在常量区
return p; // 编译器将提出警告
//return arr;
}
int main(void)
{
char *str = NULL;
str = GetString(); // str 的内容是垃圾 ( 书上如是说 )
cout << str << endl;
return 0;
}


3、至于返回了arr还可以打印出值,那是编译器销毁栈的时间与方式差异而已,换个编译器看看
Julykey 2009-12-30
  • 打赏
  • 举报
回复
很不错
wjling2009 2009-12-30
  • 打赏
  • 举报
回复
请亲自看看程序执行时的堆栈情况,你会思考很多东西的!(使用ollydbg..)
zhangyinze123 2009-12-30
  • 打赏
  • 举报
回复
栈内存当函数周期完毕,就释放了
走好每一步 2009-12-30
  • 打赏
  • 举报
回复
传说中每回一个贴就可以得十分!
camelisi 2009-12-30
  • 打赏
  • 举报
回复
受教了,荣老大
我是个菜鸟,很多东西我确实凭空思考真的无法知道
确实个人学习方法也有问题,经常是先看书,然后再自己编几个例子运行下,看自己想的跟书上讲的是不是一致,如果不一致,是什么原因
也许我说的不够清楚,我的问题其实是想问,为什么明明返回的栈指针的内存,为什么没有出现预期的错误?
我知道return p返回的是数组的首地址 所以知道cout<<str 这里相当于cout<<p
也知道栈内存上的指针和引用在函数生命周期结束后是要被内存要被销毁 返回局部指针或引用会指向不确定内存
我很想知道,你是怎么知道p是局部变量,而*p不是局部变量的?两者不都是在栈上分配的内存吗?同样p[]和*p 都是赋值为常量字符串"hello,world"。
你是通过什么样的知识积累才知道这个的?
zzw_happy 2009-12-30
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 arong1234 的回复:]
字符串是不可直接返回的,因此没用所谓的返回"hello world"之类的说法,你只能返回字符串的首地址。
当你用char p[]方式定义时,系统在堆栈上创建一个临时数组,然后把hello world内容拷贝进去,因此当你返回p时,实际是返回那个临时数组的首地址。
改成指针以后,p实际指向的是一个常量字符串"hello world",而这个字符串是在常量区永远存在的,不是临时变量。可以这么说,p是局部变量,但是*p不是
引用 5 楼 camelisi 的回复:
如果将 char p[] 改成 char *p则不会出现警告但结果始终是 hello world.
书上说 "hello world"是静态常量,在程序生命周期一直不变,所以改用*p就只会返回 hello world..

先前GC++警告说 返回了局部变量的地址 怎么改成指针就没有了呢
*p不也是局部变量吗?不解。

[/Quote]

高手,一语中的
arong1234 2009-12-30
  • 打赏
  • 举报
回复
希望大家读书时不要只是把人家的话死记硬背下来,要经常问问自己为什么。为什么临时变量的指针或引用不能返回?返回了什么时候会出错?为什么出错?如果不是直接问网络来得到答案,而是自己想出答案来,或者即使想不出答案,经过一定时间思考后问别人得到答案,自己收获一定比照抄别人的文字多得多。
arong1234 2009-12-30
  • 打赏
  • 举报
回复
字符串是不可直接返回的,因此没用所谓的返回"hello world"之类的说法,你只能返回字符串的首地址。
当你用char p[]方式定义时,系统在堆栈上创建一个临时数组,然后把hello world内容拷贝进去,因此当你返回p时,实际是返回那个临时数组的首地址。
改成指针以后,p实际指向的是一个常量字符串"hello world",而这个字符串是在常量区永远存在的,不是临时变量。可以这么说,p是局部变量,但是*p不是
[Quote=引用 5 楼 camelisi 的回复:]
如果将 char p[] 改成 char *p则不会出现警告但结果始终是 hello world.
书上说 "hello world"是静态常量,在程序生命周期一直不变,所以改用*p就只会返回 hello world..

先前GC++警告说 返回了局部变量的地址 怎么改成指针就没有了呢
*p不也是局部变量吗?不解。
[/Quote]
phpjspasp 2009-12-30
  • 打赏
  • 举报
回复
有一个人这么比喻过:闯红灯一次不一定会被车撞死。
arong1234 2009-12-30
  • 打赏
  • 举报
回复
试试下面代码



char *GetString(void)
{
char p[] = "hello world";
return p; // 编译器将提出警告
}
char * foo()
{
char buffer[128];
memset(buffer, 0xCD, 128);
return 0;
}
void Test4(void)
{
char *str = NULL;
str = GetString(); // str 的内容是垃圾 ( 书上如是说 )
foo(); //看看调用这个函数后,底下输出是什么
cout < < str < < endl;
}

camelisi 2009-12-30
  • 打赏
  • 举报
回复
如果将 char p[] 改成 char *p则不会出现警告但结果始终是 hello world.
书上说 "hello world"是静态常量,在程序生命周期一直不变,所以改用*p就只会返回 hello world..

先前GC++警告说 返回了局部变量的地址 怎么改成指针就没有了呢
*p不也是局部变量吗?不解。
ghost0088 2009-12-30
  • 打赏
  • 举报
回复
我认为有两种可能
1,"hello world" 在数据段中,并不是属于局部变量,只有返回指向他的地址。
2,在GetString()中 "hello world"是被从数据段复制到了堆栈里的,但还未被覆盖。

你可以看下汇编确定下
weixiaoshashou 2009-12-30
  • 打赏
  • 举报
回复
可能乱码,可能正常输出。指针函数返回是指向栈内存的指针,此指针的地址不为NULL,但原来的内容已被清除,新内容不可知。
kingstarer 2009-12-30
  • 打赏
  • 举报
回复
不过这里的内容肯定无法长久保存 可能你一次再调用函数就把它覆盖了
kingstarer 2009-12-30
  • 打赏
  • 举报
回复
不一定 只要这块内存没被人占用

64,649

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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