69,378
社区成员
发帖
与我相关
我的任务
分享
#include <iostream>
#include <string.h>
int getName()
{
int i = 20;
return i;
}
int main()
{
int *p;
p = &getName();
return 0;
}
ClassName getVal()
{
.....
}
int main()
{
ClassName *name;
name = &getVal();
...
return 0;
}
1 #include <stdio.h>
2 static int num = 10;
3 static int *add = NULL;
4 int get_value()
5 {
6 int temp = num;
//嵌入汇编语言,咱把局部变量的地址取出来,然后在外部使用
7 __asm__ volatile(
8 "movl %%ebp, %%edx\n\t"
9 "subl $0x4, %%edx\n\t"
10 :"=d"(add)
11 :);
12 return temp;
13 }
14 int main()
15 {
16 int i;
17
18 get_value();//获取结果为10,标志获取临时变量temp地址成功
19 printf("1 old value:%d\n", *add);
20 *add = 30;//我们使用这个临时变量,是可以使用的,得到30
21 printf("new value:%d\n", *add);
22 i = get_value();
23 printf("return value:%d\n", i);
printf("2 old value:%d\n", *add); //2次调用后,结果又刷回到10
24 return 0;
25 }
下面是gcc编译后反汇编的结果,主函数就不帖了
080483e4 <get_value>:
124 80483e4: 55 push %ebp
125 80483e5: 89 e5 mov %esp,%ebp
126 80483e7: 83 ec 10 sub $0x10,%esp
127 80483ea: a1 14 a0 04 08 mov 0x804a014,%eax
128 80483ef: 89 45 fc mov %eax,-0x4(%ebp)
129 80483f2: 89 ea mov %ebp,%edx//这4句是我加的内容,得到%ebp-0x4地址,因为整数占4B(32bit)
130 80483f4: 83 ea 04 sub $0x4,%edx
131 80483f7: 89 d0 mov %edx,%eax
132 80483f9: a3 20 a0 04 08 mov %eax,0x804a020
133 80483fe: 8b 45 fc mov -0x4(%ebp),%eax
134 8048401: c9 leave
135 8048402: c3 ret
当然如果嵌入汇编不好理解,你可以直接取地址像这样
int get_value()
5 {
6 int temp = num;
12 add = &temp;
13 return temp;
14 }
效果是一样的
我这样做并不是鼓励你去使用或者引用临时变量,而是让你清楚几点:
1. 内存在函数调用的表达式结束后就回收了. 回收并不代表内存就不可用了. 内存还在.这里的回收意思可作为空闲区由系统分配。(比如我在主函数里使用它)
2. 函数的局部变量内存是在栈里面的, 不在文件的Data段.(mov %esp,%ebp可证明)
3. 临时变量生命期由函数的返回,弹出栈操作回到调用函数,而让用户不再拥有看到局部变量的地址而算作“消亡”。其实这点算作第1点的补充,所以“消亡”要加引号。
4. 记住不要在外使用“消亡”的临时变量
哦了,就说这么多吧。
2 #include <stdio.h>
3 #include <string.h>
4 int getName()
5 {
6 int i = 20;
7 return i;
8 }
9 int main()
10 {
11 int *p;
12 *p = getName();
13 return 0;
14 }
gcc编译后,反汇编得到的结果
80483b4 <getName>:
119 80483b4: 55 push %ebp
120 80483b5: 89 e5 mov %esp,%ebp//
121 80483b7: 83 ec 10 sub $0x10,%esp
122 80483ba: c7 45 fc 14 00 00 00 movl $0x14,-0x4(%ebp)
123 80483c1: 8b 45 fc mov -0x4(%ebp),%eax//here1
/*很显然here1它把返回值放到了寄存器eax中,然后有主函数中here2存到对应的变量中去。
也就说这个操作执行后,函数getname中局部变量-0x4(%ebp),已经不再重要了,
因为它的值已经转移走了。系统可以用他干别的事情了。而且它是在栈里面的,局部于%ebp
在进入函数的时候push %ebp保存调用函数地址;mov %esp,%ebp转向被调用函数栈指针*/
124 80483c4: c9 leave
125 80483c5: c3 ret
126
127 080483c6 <main>:
128 80483c6: 55 push %ebp
129 80483c7: 89 e5 mov %esp,%ebp
130 80483c9: 83 ec 10 sub $0x10,%esp
131 80483cc: e8 e3 ff ff ff call 80483b4 <getName>
132 80483d1: 8b 55 fc mov -0x4(%ebp),%edx
133 80483d4: 89 02 mov %eax,(%edx)//here2
134 80483d6: b8 00 00 00 00 mov $0x0,%eax
135 80483db: c9 leave
136 80483dc: c3 ret
137 80483dd: 90 nop
138 80483de: 90 nop
139 80483df: 90 nop