问个比较掉价的问题

梦是多么的重要 2014-08-06 04:56:22

如下程序

#include <iostream>
class A
{
public :
char * test();
private:
char *m;
};

char * A::test()
{
m = "1234567890";
}

char * test()
{
char *m = "0987654321";
}

void main()
{
A a;
char * m = a.test();
std::cout << m; //函数生命周期结束了,栈区数据怎么还在,我靠,没出问题? 以前一直用智能指针,没在意这个,今天看代码发现这么个问题;

m = test(); //函数生命周期结束了,栈区数据怎么还在,我靠,没出问题? 以前一直用智能指针,没在意这个,今天看代码发现这么个问题;
std::cout <<m;
}








这问题有点掉价啊.....
...全文
602 30 打赏 收藏 转发到动态 举报
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
jmppok 2014-08-07
  • 打赏
  • 举报
回复
引用 1 楼 wanght99 的回复:
"1234567890" 这种字符串直接量是在常量区的, 这个数据不会丢失的. 我觉得略奇特的是, 你不觉得你的test没有return语句么?
+1 确定程序能编译通过?
  • 打赏
  • 举报
回复
引用 23 楼 luoxuechengbing 的回复:
[quote=引用 21 楼 zjq9931 的回复:] [quote=引用 19 楼 luoxuechengbing 的回复:] …………我不是这个意思,可能我表达错误………我就是想说,常量的数据保存在哪里. 栈上只有常量的地址了!!!!
如果是VC的话,跟踪的时候,按ALT+8,看汇编代码。里面有常量的地址。 然后ALT+6,可以看相应内存地址的内容。[/quote]
引用 18 楼 wanght99 的回复:
[quote=引用 15 楼 luoxuechengbing 的回复:] [quote=引用 14 楼 wanght99 的回复:] [quote=引用 12 楼 luoxuechengbing 的回复:] [quote=引用 9 楼 henry3695 的回复:] 你这是在常量区域 执行一次后,就在那里待着了 到程序结束吧
不应该是这样的, 你可以试试一个数组... 一样也在 ... 我的回答是 和 10L星哥一样的,不安全... [/quote] 是的, 数组也可能在, 你那个字符串直接量是在常量区没有错, 同样的现象不同的道理. 在栈里局部变量退出的时候只是改栈指针而已, 之前的数据不会主动覆盖, 不安全. 但你的程序里的那个m指针, 是安全的. 不冲突[/quote] 为什么常量区的数据就不会结束呢? 百度了下,看到资料说是拷贝了份,这个时候栈区只是存在了一个地址了~![/quote] 因为m是指针, 字符串常量是编译时就确定的, 可以理解为编译时专门为它分配了空间, 程序里给m赋值的时候就是让m指向它.. 给m赋值的时候关于那个字符串没有任何分配空间的动作. 当然也就无从回收.[/quote]
引用 10 楼 starytx 的回复:
数据在说明栈还没有被重新使用,不代表这样就是安全的吧
http://blog.chinaunix.net/uid-25002135-id-2974174.html找到答案了哈~![/quote] 支持分享。
lm_whales 2014-08-07
  • 打赏
  • 举报
回复
,也就是执行 m= "0123456789" 的时候,"0123456789" 的地址, 即(指针)m的值,残留在寄存器中,函数调用结束后,得到的是寄存器中的值, 也就是函数内部,表达式m= "0123456789" 计算的残留的值。 PS: 记住,如果非构造函数,没有写return 语句 ,通常函数返回值。 就是计算的中间结果,残留在寄存器中的值, 根据返回值类型不同,硬件系统,操作系统, 还有编译器的不同等等,结果可能是不同的。 一句话,结果不确定
lm_whales 2014-08-07
  • 打赏
  • 举报
回复
有返回值的函数,应该明确写上return 语句,不然结果是不确定的.
lm_whales 2014-08-07
  • 打赏
  • 举报
回复
因为返回值,往往通过寄存器传递。 你的函数没写return 语句,返回值差不多就是寄存器中残留的值 其实,也就是执行 m= "0123456789" 的时候,地址 m的值残留到寄存器中了, 因为表达式求值,也可能会使用这个寄存器 ,,,,VC,本机代码,X86,32Bits 这个寄存器是 eax 具体,可以查看对应的汇编代码。 在编译器中,可以设置警告以及错误等级,等等编译选项 随着编译选项的设置不同,编译结果不尽相同 通常,这种不写return语句的函数,会有警告或者出错信息。 另外,release 版本,test() 后面的输出语句,可能会输出不确定的结果。 因为 代码char *m = "0987654321"; 对于 test()属于无用代码,优化时,可以直接忽略,不生成任何代码。 建议,每个带返回值的函数,都要写return语句。 多分支返回的函数,一定不要忘记写最后的那个return语句。
shenlanzifa 2014-08-07
  • 打赏
  • 举报
回复
C/C++编译的程序占用的内存分为以下几个区域: 1、栈区(stack) 由系统自动分配和释放,用于存放函数的参数值,局部变量值等。其在内存中是一块连续的存储区域,由低地址向高地址延伸。 2、堆区(heap) 由程序员分配和释放,若程序员不释放,则程序结束时可能由操作系统回收。其存储空间在内存中是不连续,分配方式类似于链表。 3、静态区(static) 又称全局区,程序结束后由系统释放,用于存放全局变量和静态变量。初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量则存储在相邻的另一块区域。 4、文字常量区 程序结束后由系统释放,用于存储常量,字符串常量就是放在这里的。 5、程序代码区 存放函数体的二进制代码。 很明显,你的数据是存放在常量区的,程序结束后才会有系统释放。
猪头十二 2014-08-07
  • 打赏
  • 举报
回复
什么鸡巴玩意
  • 打赏
  • 举报
回复
引用 21 楼 zjq9931 的回复:
[quote=引用 19 楼 luoxuechengbing 的回复:] …………我不是这个意思,可能我表达错误………我就是想说,常量的数据保存在哪里. 栈上只有常量的地址了!!!!
如果是VC的话,跟踪的时候,按ALT+8,看汇编代码。里面有常量的地址。 然后ALT+6,可以看相应内存地址的内容。[/quote]
引用 18 楼 wanght99 的回复:
[quote=引用 15 楼 luoxuechengbing 的回复:] [quote=引用 14 楼 wanght99 的回复:] [quote=引用 12 楼 luoxuechengbing 的回复:] [quote=引用 9 楼 henry3695 的回复:] 你这是在常量区域 执行一次后,就在那里待着了 到程序结束吧
不应该是这样的, 你可以试试一个数组... 一样也在 ... 我的回答是 和 10L星哥一样的,不安全... [/quote] 是的, 数组也可能在, 你那个字符串直接量是在常量区没有错, 同样的现象不同的道理. 在栈里局部变量退出的时候只是改栈指针而已, 之前的数据不会主动覆盖, 不安全. 但你的程序里的那个m指针, 是安全的. 不冲突[/quote] 为什么常量区的数据就不会结束呢? 百度了下,看到资料说是拷贝了份,这个时候栈区只是存在了一个地址了~![/quote] 因为m是指针, 字符串常量是编译时就确定的, 可以理解为编译时专门为它分配了空间, 程序里给m赋值的时候就是让m指向它.. 给m赋值的时候关于那个字符串没有任何分配空间的动作. 当然也就无从回收.[/quote]
引用 10 楼 starytx 的回复:
数据在说明栈还没有被重新使用,不代表这样就是安全的吧
http://blog.chinaunix.net/uid-25002135-id-2974174.html找到答案了哈~!
  • 打赏
  • 举报
回复
引用 17 楼 zhao4zhong1 的回复:
计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构…… 对学习编程者的忠告: 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步对应汇编一行! VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。 对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。 (Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
不变应万变的赵老师好 答案我找到了:http://blog.chinaunix.net/uid-25002135-id-2974174.html
  • 打赏
  • 举报
回复
引用 19 楼 luoxuechengbing 的回复:
…………我不是这个意思,可能我表达错误………我就是想说,常量的数据保存在哪里. 栈上只有常量的地址了!!!!
如果是VC的话,跟踪的时候,按ALT+8,看汇编代码。里面有常量的地址。 然后ALT+6,可以看相应内存地址的内容。
  • 打赏
  • 举报
回复
汇编代码:

12:       m = "1234567890";
0040116D   mov         eax,dword ptr [ebp-4]
00401170   mov         dword ptr [eax],offset string "1234567890" (0043201c)

18:       char *m = "0987654321";
004011A8   mov         dword ptr [ebp-4],offset string "0987654321" (0043202c)
返回的是内存中的这两个地址: 0043202c 0043201c 只要内存中这两个地址中的内容没有销毁,那么,这个值就一直可以用。
  • 打赏
  • 举报
回复
…………我不是这个意思,可能我表达错误………我就是想说,常量的数据保存在哪里. 栈上只有常量的地址了!!!!
wanght99 2014-08-06
  • 打赏
  • 举报
回复
引用 15 楼 luoxuechengbing 的回复:
[quote=引用 14 楼 wanght99 的回复:] [quote=引用 12 楼 luoxuechengbing 的回复:] [quote=引用 9 楼 henry3695 的回复:] 你这是在常量区域 执行一次后,就在那里待着了 到程序结束吧
不应该是这样的, 你可以试试一个数组... 一样也在 ... 我的回答是 和 10L星哥一样的,不安全... [/quote] 是的, 数组也可能在, 你那个字符串直接量是在常量区没有错, 同样的现象不同的道理. 在栈里局部变量退出的时候只是改栈指针而已, 之前的数据不会主动覆盖, 不安全. 但你的程序里的那个m指针, 是安全的. 不冲突[/quote] 为什么常量区的数据就不会结束呢? 百度了下,看到资料说是拷贝了份,这个时候栈区只是存在了一个地址了~![/quote] 因为m是指针, 字符串常量是编译时就确定的, 可以理解为编译时专门为它分配了空间, 程序里给m赋值的时候就是让m指向它.. 给m赋值的时候关于那个字符串没有任何分配空间的动作. 当然也就无从回收.
赵4老师 2014-08-06
  • 打赏
  • 举报
回复
计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构…… 对学习编程者的忠告: 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步对应汇编一行! VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。 对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。 (Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
赵4老师 2014-08-06
  • 打赏
  • 举报
回复
其实电脑开机后物理内存的每个字节都是可读写的,区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页,一页通常为4KB。
  • 打赏
  • 举报
回复
引用 14 楼 wanght99 的回复:
[quote=引用 12 楼 luoxuechengbing 的回复:] [quote=引用 9 楼 henry3695 的回复:] 你这是在常量区域 执行一次后,就在那里待着了 到程序结束吧
不应该是这样的, 你可以试试一个数组... 一样也在 ... 我的回答是 和 10L星哥一样的,不安全... [/quote] 是的, 数组也可能在, 你那个字符串直接量是在常量区没有错, 同样的现象不同的道理. 在栈里局部变量退出的时候只是改栈指针而已, 之前的数据不会主动覆盖, 不安全. 但你的程序里的那个m指针, 是安全的. 不冲突[/quote] 为什么常量区的数据就不会结束呢? 百度了下,看到资料说是拷贝了份,这个时候栈区只是存在了一个地址了~!
wanght99 2014-08-06
  • 打赏
  • 举报
回复
引用 12 楼 luoxuechengbing 的回复:
[quote=引用 9 楼 henry3695 的回复:] 你这是在常量区域 执行一次后,就在那里待着了 到程序结束吧
不应该是这样的, 你可以试试一个数组... 一样也在 ... 我的回答是 和 10L星哥一样的,不安全... [/quote] 是的, 数组也可能在, 你那个字符串直接量是在常量区没有错, 同样的现象不同的道理. 在栈里局部变量退出的时候只是改栈指针而已, 之前的数据不会主动覆盖, 不安全. 但你的程序里的那个m指针, 是安全的. 不冲突
  • 打赏
  • 举报
回复
引用 9 楼 henry3695 的回复:
你这是在常量区域 执行一次后,就在那里待着了 到程序结束吧
的确是常量了。。。。但是 能给点资料吗 常量类型的为什么要等到程序结束才会释放?
  • 打赏
  • 举报
回复
引用 9 楼 henry3695 的回复:
你这是在常量区域 执行一次后,就在那里待着了 到程序结束吧
不应该是这样的, 你可以试试一个数组... 一样也在 ... 我的回答是 和 10L星哥一样的,不安全...
starytx 2014-08-06
  • 打赏
  • 举报
回复
数据在说明栈还没有被重新使用,不代表这样就是安全的吧
加载更多回复(9)

64,654

社区成员

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

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