免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: donotblock

还有人搞不清楚这个问题么? [复制链接]

论坛徽章:
0
发表于 2010-11-22 09:51 |显示全部楼层
两个问题
1.就是之前有位仁兄说的变量生存周期的问题,局部变量过期,被回收后指针所指向的地址的值是不存 ...
scgywx 发表于 2010-11-22 00:28



    内存空间也可以在getdata里面申请分配

论坛徽章:
0
发表于 2010-11-22 10:00 |显示全部楼层
回复 31# donotblock


    也可以啊!但是你必须保证指针指向的地方是正确的。

论坛徽章:
0
发表于 2010-11-22 14:07 |显示全部楼层
2为什么是可以的?

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:56:11
发表于 2010-11-22 21:20 |显示全部楼层
其实这问题,实践一下就明了。没有什么好说的,就是多看,多写。

论坛徽章:
0
发表于 2010-11-22 22:08 |显示全部楼层
本帖最后由 BJSH 于 2010-11-22 22:16 编辑
虽然我很清楚不能像1里面那样使用,但我奇怪的是编译器出于什么样一种优化决策,1里面的自动变量 ...
donotblock 发表于 2010-11-22 09:48


这和优化没关系, 只是你的测试代码 还没有更改那块栈空间而已


getint:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $16, %esp
        movl    $10, -4(%ebp)
        movl    8(%ebp), %eax
        leal    -4(%ebp), %edx
        movl    %edx, (%eax)
        movl    $0, %eax
        leave
        ret

c 调用函数最开始会让EBP指向栈底, 然后ESP会在最开始就偏移一定的空间, 取决于该函数的局部变量和需要调用的函数的参数以及字节对齐的问题

局部变量会在栈底分配, 比如getint的局部变量 i 的空间就是 -4(%ebp), EBP下的四字节空间

调用函数的参数 会在栈顶算偏移写入栈中
看看main函数调用printf的过程
.LC1:
        .string "%d\n"
....
        movl    $.LC1, %eax
        movl    %edx, 4(%esp)                ;printf的第二个参数
        movl    %eax, (%esp)                  ;printf的第一个参数 %d\n
        call    printf


我要说的是, 栈底和栈顶还有一段空间,


    void * p = NULL;
    getint(&p);
    printf("%d\n", *(int *)p);

不要认为调用printf后, getint中的栈空间就完全被覆盖掉了。 正是因为这段空间, getint中的局部变量 i 才没有被覆盖。 这不是编译器的什么优化

假如:
    void * p = NULL;
    void * p1 = NULL;
    getint(&p);
    getstring(&p1);
    printf("%d\n", *(int *)p);
    printf("%s\n", (char *)p1);

在getint后 调用一下其它的函数, 然后再打印, 你看看 还是不是10,

甚至你还可以精心构造去改变那块栈空间

比如:

int getint(void **p){
    int i = 10;
    (*p) = &i;
    return 0;
}

int getstring2(void **p){
   char s[] = {0x12,0x34,0x56,0x78};
   (*p) = s;
   return 0;
}

int main(int argc, char * argv[])
{
    void * p = NULL;
    void * p1 = NULL;
    getint(&p);
    getstring2(&p1);
    printf("%X\n", *(int *)p);
    printf("%s\n", (char *)p1);
    return 0;
}


在getstring2中讲那四字节空间改为 0x12, 0x34, 0x56, 0x78

输出结果不是10 而是 : %x : 78563412



================================
或者这么说, 在你调用printf之前, 给printf的参数已经被复制到了 栈底的上方, 调用printf后确实会把getint的栈空间覆盖掉, 但是执行过程中用到的是EBP上方的参数, 而不再是原来的位置

比如:
nt main(int argc, char * argv[])
{
    void * p = NULL;
    getint(&p);
    printf("%d\n", *(int *)p);
    printf("%d\n", *(int *)p);
    return 0;
}

连续打印两次, 第一次是10, 第二次就不再是了。

论坛徽章:
0
发表于 2010-11-22 22:27 |显示全部楼层
这和优化没关系, 只是你的测试代码 还没有更改那块栈空间而已


getint:
        pushl   %ebp
  ...
BJSH 发表于 2010-11-22 22:08



    很好,很清楚,谢谢

论坛徽章:
0
发表于 2010-11-22 22:30 |显示全部楼层
2为什么是可以的?
kutong 发表于 2010-11-22 14:07



    char *p 指向的是常量字符串,不可修改。这种字符串一般会放在数据段中(我没找到明确文档说一定),不是动态分配在栈上,所以函数退出,地址仍然有效。

论坛徽章:
0
发表于 2010-11-23 08:57 |显示全部楼层
2 是可以的, 1不行, 即使正确输出, 也只是表示那时候 那块栈空间还没有被破坏而已。

  
  不 ...
BJSH 发表于 2010-11-21 13:10



    那么想学这些知识,应该看哪些书呢?

论坛徽章:
0
发表于 2010-11-23 09:25 |显示全部楼层
那么想学这些知识,应该看哪些书呢?
kutong 发表于 2010-11-23 08:57



    汇编(不用太深入,看懂代码即可),深入理解计算机系统 。

论坛徽章:
0
发表于 2010-11-23 09:28 |显示全部楼层
汇编(不用太深入,看懂代码即可),深入理解计算机系统 。
donotblock 发表于 2010-11-23 09:25



   深入理解计算机系统我倒是有一本,一直也没看,太厚了
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

DTCC2020中国数据库技术大会

【架构革新 高效可控】2020年12月21日-23日第十一届中国数据库技术大会将在北京隆重召开。

大会设置2大主会场,20+技术专场,将邀请超百位行业专家,重点围绕数据架构、AI与大数据、传统企业数据库实践和国产开源数据库等内容展开分享和探讨,为广大数据领域从业人士提供一场年度盛会和交流平台。

http://dtcc.it168.com


大会官网>>
  

北京盛拓优讯信息技术有限公司. 版权所有 16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122
中国互联网协会会员  联系我们:huangweiwei@it168.com
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP