这样为什么不会发生访问内存失败

hackbuteer1 2011-08-23 07:49:13
#include "iostream"
#include "string"
using namespace std;

char *GetMemory( void )
{
char p[] = "hello world";
return p;
}

void Test( void )
{
char *str = NULL;
str = GetMemory();
cout<<*(str+6)<<endl; //这里可以遍历hello world这个字符串
}

int main(void)
{
Test();
system("pause");
return 0;
}

GetMemory函数内部的p数组是栈上的临时变量,函数返回后就销毁了。。
为什么下面的代码
cout<<*str<<endl;
cout<<*(str+1)<<endl;
。。。。。。
cout<<*(str+10)<<endl; 这样可以遍历输出hello world 整个字符串,这个字符串是栈上的临时变量,函数返回后就销毁了,str不应该可以访问到的啊。。
还有就是cout<<*(str+15)<<endl; 都可以输出,而且还没有编译错误,15已经远远超出了hello world的长度了啊。。
很奇怪啊。。。。
...全文
254 29 打赏 收藏 转发到动态 举报
写回复
用AI写文章
29 条回复
切换为时间正序
请发表友善的回复…
发表回复
shujiezhang 2011-08-24
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 bokutake 的回复:]

引用 2 楼 pathletboy 的回复:

"hello world"字串是全局的,所以 char p[] 虽然是局部变量,但是函数最后返回的是全局的一个地址,不影响内存访问,另外任何内存访问越界不一定会导致出错。


不对,如果它写成char p* = "hello world";
这样的话,p是指针指向字符串字面量,这个是全局的常量,不会被销毁。
但是如果是char p[]……
[/Quote]

char p[]的内容是在栈上的,函数调用结束,只是对esp指针进行sub操作,不会销毁栈上的内容,所以你通过返回的p这个指针还能访问到栈上的内容,因为getmemory函数调用结束后你没有调用别的函数,所以栈也没有被覆盖。

你在getmemory后边再调用其他函数,结果就不同了。
luciferisnotsatan 2011-08-24
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 taodm 的回复:]

楼主,能跑是因为你人品好。
但是,一个人不可能一直人品好。
[/Quote]
我倒觉得是人品不好。自己没测出,等发不出去了,用户发现了,修正成本就大大增加了。
hackbuteer1 2011-08-24
  • 打赏
  • 举报
回复
[Quote=引用 26 楼 news080 的回复:]
因为你用的是XP系统!
[/Quote]

不是的,我用的是windows 7系统。。
HelloGameProgramer 2011-08-24
  • 打赏
  • 举报
回复
因为你用的是XP系统!
hackbuteer1 2011-08-24
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 zhaoxukun 的回复:]
关于楼主提出的问题,我可以这样为你解答。
首先你得熟悉一下c/c++内存管理方面的知识,变量的存放可以分为这几个区域:堆栈区,堆区,静态存储区域,常量区域。在堆栈中存放的是局部变量,包括函数的形参等。那么这样的变量在函数结束时,它所 占用的内存空间就会被自动释放掉。(注意这里的局部变量不能是常量,也不能是静态变量)堆区里占用的空间是程序用malloc函数或用new运算符分配的,这个得要程序员自动……
[/Quote]

cout << str<< endl;
的确不能打印hello world,输出的xP,很奇怪,不知道为什么是xP??
另外就是cout << *(str+6) << endl; 输出的是w ,这里可以遍历hello world这个字符串
为什么输出的是w,为什么这样就可以访问hello world了,hello world已经销毁了啊。。。
LONWORKS 2011-08-24
  • 打赏
  • 举报
回复
正解。[Quote=引用 19 楼 zhaoxukun 的回复:]
关于楼主提出的问题,我可以这样为你解答。
首先你得熟悉一下c/c++内存管理方面的知识,变量的存放可以分为这几个区域:堆栈区,堆区,静态存储区域,常量区域。在堆栈中存放的是局部变量,包括函数的形参等。那么这样的变量在函数结束时,它所 占用的内存空间就会被自动释放掉。(注意这里的局部变量不能是常量,也不能是静态变量)堆区里占用的空间是程序用malloc函数或用new运算符分配的,这个得要程序员自动……
[/Quote]
modicum_lf 2011-08-24
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 ljljlj 的回复:]

你扔垃圾筒里的东西并不代表你不可以再捡回来,但更不代表你去捡时,垃圾就一定还在那,因为垃圾可能已经被别人倒掉。
[/Quote]

++

ljhhh0123 2011-08-24
  • 打赏
  • 举报
回复
你扔垃圾筒里的东西并不代表你不可以再捡回来,但更不代表你去捡时,垃圾就一定还在那,因为垃圾可能已经被别人倒掉。
圣诞老人123 2011-08-24
  • 打赏
  • 举报
回复
内存销毁不是擦除~~,销毁是让计算机不记得那里有什么,该段地址上知道下次被覆盖前都是这个值.这和删除文件后用工具能恢复数据差不多么~~~
hdskycai 2011-08-24
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 zhaoxukun 的回复:]
关于楼主提出的问题,我可以这样为你解答。
首先你得熟悉一下c/c++内存管理方面的知识,变量的存放可以分为这几个区域:堆栈区,堆区,静态存储区域,常量区域。在堆栈中存放的是局部变量,包括函数的形参等。那么这样的变量在函数结束时,它所 占用的内存空间就会被自动释放掉。(注意这里的局部变量不能是常量,也不能是静态变量)堆区里占用的空间是程序用malloc函数或用new运算符分配的,这个得要程序员自动……
[/Quote]

19楼正解!!
程序人生 2011-08-24
  • 打赏
  • 举报
回复
关于楼主提出的问题,我可以这样为你解答。
首先你得熟悉一下c/c++内存管理方面的知识,变量的存放可以分为这几个区域:堆栈区,堆区,静态存储区域,常量区域。在堆栈中存放的是局部变量,包括函数的形参等。那么这样的变量在函数结束时,它所 占用的内存空间就会被自动释放掉。(注意这里的局部变量不能是常量,也不能是静态变量)堆区里占用的空间是程序用malloc函数或用new运算符分配的,这个得要程序员自动使用系统提供的free函数或delete运算符进行释放,如果程序不再用完后释放这些内存,那么就会产生内存泄露。所以使用堆区的生命周期完全控制在free函数或delete运算符手里。那么,我们程序中的全局变量和静态变量是存储在静态存储区域中的,所以它的生命周期只有当我们的应用程序结束的时候才会终止,同理,常量区域是存放常量的。从常量所占用内存的生命周期来讲,不管是全局的常量还是局部的常量,一经定义它会一致占用这片内存,同样直到程序结束时才会释放。
了解了上面的基础知识后,我们就不难回答你的问题了。
char p[] = "hello world";这行代码相当于char p[]={"hello world"};但这里“hello world”可不是常量,它只是给这个数组元素赋值,因为这里是局部变量,所以你的代码在函数调用结束后p指向的内存会被释放,它所指向的内存单元的值会变成随机值,尽管你还可以访问这个内存单元。不信你试试下面这行代码
cout<<str<<endl;它要是能完整的打印出"hello world",我跟你姓!
但是如果上面的定义改成:char *p = "hello world";就相当于栈指针指向了常量区,你怎么访问都可以,
在程序结束前它肯定不会被释放。但是注意不能修改它的值!
hackbuteer1 2011-08-23
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 xjx_2004 的回复:]
返回局部变量的地址
[/Quote]
局部变量是在栈上面的,返回后就销毁了。。
TomByTed 2011-08-23
  • 打赏
  • 举报
回复
返回局部变量的地址
hackbuteer1 2011-08-23
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 mougaidong 的回复:]
C/C++ code

#include "iostream"
#include "string"

using namespace std;

char *GetMemory( void )
{
char p[] = "hello world";
return p;
}

char *Test( void )
{
char *str = ……
[/Quote]
你的程序我运行过了,感觉很奇怪啊。。
输出的是:
1
w
1
第4个值每次运行输出的都是不一样的,很奇怪啊。。。
hackbuteer1 2011-08-23
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 tujiaw 的回复:]
这个肯定不行的, 内存会被销毁的, 返回的指针是一个野指针,所以结果是不可测的
[/Quote]
结果确实是可以遍历那个字符串的,很奇怪啊,你可以运行一下的。。。
ningto.com 2011-08-23
  • 打赏
  • 举报
回复
这个肯定不行的, 内存会被销毁的, 返回的指针是一个野指针,所以结果是不可测的
pathuang68 2011-08-23
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 taodm 的回复:]

楼主,能跑是因为你人品好。
但是,一个人不可能一直人品好。
[/Quote]

++

hackbuteer1 2011-08-23
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 yah606060 的回复:]
char p[] = "hello world" 这个内存会被销毁吧。。 还能访问?
[/Quote]

还是可以访问的,你可以运行一下的。。。
hackbuteer1 2011-08-23
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 pathletboy 的回复:]
"hello world"字串是全局的,所以 char p[] 虽然是局部变量,但是函数最后返回的是全局的一个地址,不影响内存访问,另外任何内存访问越界不一定会导致出错。
[/Quote]
函数最后返回的是全局的一个地址????
你的这个说法我不同意,这个是p数组是在栈上临时申请的局部变量,函数返回的应该是这个在栈上开辟的空间的地址。。。
hackbuteer1 2011-08-23
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 babilife 的回复:]
引用楼主 hackbuteer1 的回复:
C/C++ code
#include "iostream"
#include "string"
using namespace std;

char *GetMemory( void )
{
char p[] = "hello world";
return p;
}

void Test( void )
{
char *st……
[/Quote]

我的编译器是VS2008,跟你的输出结果是一样的,都是输出w
加载更多回复(9)

64,683

社区成员

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

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