作者:菜鸟自学编程 | 来源:互联网 | 2024-10-23 17:44
如下程序
#include
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 <
}
这问题有点掉价啊.....
30 个解决方案
"1234567890"
这种字符串直接量是在常量区的, 这个数据不会丢失的.
我觉得略奇特的是, 你不觉得你的test没有return语句么?
你的m是一个main里的指针,main还没有结束啊,
函数结束,又不会改变m指向的内存的数据,
还有一点,你命名能养成好的习惯吗?
纯在网页手打而已.....不是跑过的,随手敲一遍而已
好像test()没有返回值啊,这样怎么给m赋值呢?
生命周期结束了,但是数据还是在那个地方的。指针销毁了而已吧?但是地址已经传递出去了,no problem
你这是在常量区域
执行一次后,就在那里待着了
到程序结束吧
数据在说明栈还没有被重新使用,不代表这样就是安全的吧
其实电脑开机后物理内存的每个字节都是可读写的,区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页,一页通常为4KB。
计算机组成原理→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对应的汇编并单步执行观察相应内存和寄存器变化。)
…………我不是这个意思,可能我表达错误………我就是想说,常量的数据保存在哪里. 栈上只有常量的地址了!!!!
C/C++编译的程序占用的内存分为以下几个区域:
1、栈区(stack)
由系统自动分配和释放,用于存放函数的参数值,局部变量值等。其在内存中是一块连续的存储区域,由低地址向高地址延伸。
2、堆区(heap)
由程序员分配和释放,若程序员不释放,则程序结束时可能由操作系统回收。其存储空间在内存中是不连续,分配方式类似于链表。
3、静态区(static)
又称全局区,程序结束后由系统释放,用于存放全局变量和静态变量。初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量则存储在相邻的另一块区域。
4、文字常量区
程序结束后由系统释放,用于存储常量,字符串常量就是放在这里的。
5、程序代码区
存放函数体的二进制代码。
很明显,你的数据是存放在常量区的,程序结束后才会有系统释放。
因为
返回值,往往通过寄存器传递。
你的函数
没写return 语句,返回值差不多就是
寄存器中残留的值
其实,也就是执行
m= "0123456789" 的时候,地址 m的值残留到寄存器中了,
因为表达式求值,也可能会使用这个寄存器
,,,,VC,本机代码,X86,32Bits 这个寄存器是 eax
具体,可以查看对应的汇编代码。
在编译器中,可以设置警告以及错误等级,等等编译选项
随着编译选项的设置不同,编译结果不尽相同
通常,这种不写return语句的函数,会有警告或者出错信息。
另外,release 版本,test() 后面的输出语句,可能会输出不确定的结果。
因为 代码char *m = "0987654321";
对于 test()属于无用代码,优化时,可以直接忽略,不生成任何代码。
建议,每个带返回值的函数,都要写return语句。
多分支返回的函数,一定不要忘记写最后的那个return语句。
有返回值的函数,应该明确写上return 语句,不然结果是不确定的.
,也就是执行 m= "0123456789" 的时候,"0123456789" 的地址,
即(指针)m的值,残留在寄存器中,函数调用结束后,得到的是寄存器中的值,
也就是函数内部,表达式m= "0123456789" 计算的残留的值。
PS:
记住,如果非构造函数,没有写return 语句 ,通常函数返回值。
就是计算的中间结果,残留在寄存器中的值,
根据返回值类型不同,硬件系统,操作系统,
还有编译器的不同等等,结果可能是不同的。
一句话,结果不确定