免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 2725 | 回复: 11
打印 上一主题 下一主题

c参数的生存周期的疑问 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-01-08 22:19 |只看该作者 |倒序浏览
我知道c语言中每个函数在调用过程中都存在一个调用栈帧,

如下所示:
  

            第一个参数
          ----------------
           第二个参数
         -----------------
               . . .  .
          ---------------
          返回地址
          --------------
         pushl   %ebp
         movl     %esp, %ebp
           .  .    .   
           ..........
         movl    %ebp, %esp
         popl    %ebp
         ret

从上面的过程可以得出以下2点:

  1)   函数的局部变量在    movl    %ebp, %esp   之后就消亡了。


   2)  ret指令的作用是将esp指针所指向的内容弹出到eip中从而实现函数的返回,也就说esp指针现在是指向最后入栈的

          那个参数的。


这里就产生了问题
      
      若第二点是正确的,也就说函数的参数没有随着函数调用的结束而消亡,反而继续存在栈中。试想如果函数调用很多(这里不是说在函数的嵌套调用),

     那么这些函数的参数都留在栈中,是否会存在这种情况:进程的整个地址空间都被函数的参数占据,导致程序崩溃。或者说函数的调用次数是有限制的。

     进一步讲,在linux内核中,在内核空间运行的程序只有两页大小的内核栈,这种情况带来的危险岂不是更严重?
      


    不知道我上面的分析对不对,望高手给出解答

论坛徽章:
0
2 [报告]
发表于 2011-01-08 22:25 |只看该作者
回复 1# bigfeng12


    ret N   N是弹出的字节数  所以用这种方法完全可以清空参数列表。

当然还有一种方法,就是

  push  arg1
  push  arg2
  call    func1
  sub   esp,8  //在这里清空参数栈

论坛徽章:
0
3 [报告]
发表于 2011-01-08 22:50 |只看该作者
编译器反汇编后每个函数的形式都是:
  
         pushl   %ebp
         movl     %esp, %ebp
           .  .    .   
           ..........
         movl    %ebp, %esp
         popl    %ebp
         ret

没有见过 ret N这种形式

论坛徽章:
0
4 [报告]
发表于 2011-01-08 23:15 |只看该作者
回复 3# bigfeng12


linux下面应该用第二种方法较多。
当年写8086的汇编的时候,我们都用第一种方法清除参数

论坛徽章:
0
5 [报告]
发表于 2011-01-13 15:26 |只看该作者
不知道有没有哥们有跟我一样的困惑,先顶一个

论坛徽章:
2
CU十二周年纪念徽章
日期:2013-10-24 15:41:34处女座
日期:2013-12-27 22:22:41
6 [报告]
发表于 2011-01-14 00:06 |只看该作者
看了半天才看懂LZ的意思。。。。参数不需要了,ESP挪一下就行了,编译器应该搞得定。我印象中,编译有时会先算一下需要多少栈空间。

论坛徽章:
0
7 [报告]
发表于 2011-01-14 06:56 |只看该作者
不用担心,编译器已经考虑到这些情况了。就像前面几楼说的,调用完清一下就可以。超级简单。

论坛徽章:
0
8 [报告]
发表于 2012-09-17 10:21 |只看该作者
在我的Fedora Linux上我写了如下的测试程序:



    .section   .text
   
     .globle  main

main:
       pushl    $str
       call    printf
       call    my_printf
       pusl   $0
       call exit
            

    .section   .data
str:
      .string   "hello world !"

.section   .text

my_printf:

      pushl    %ebp
      movl     %esp , %ebp
      movl    (%esp + ,%ecx
      movl    $1,     %ebx
      movl    $12,   %edx
      movl     $4,%eax
      int      $0x80
      movl    %ebp, %esp
      popl     %ebp
      ret

结果出现两次hello world!

也就是说调用printf后其参数$str还是存在栈中的, 跟楼上大牛们说的不一样呀!

论坛徽章:
0
9 [报告]
发表于 2012-09-17 10:24 |只看该作者
不好意思,有点罗索

   

论坛徽章:
0
10 [报告]
发表于 2012-09-18 10:02 |只看该作者
楼主,对简直无语了,esp 调整回来之后,数值重新开始啦,后面的函数调用会覆盖前一次的函数调用使用的栈了。怎么会一直保留这呢。


就像100米赛跑,难道因为多跑了几个小组赛,最后的决赛的时候,100跑道就不够长啦?


你写多几个函数调用,然后单指令跟踪看一下esp 和ebp的值


myprint()
myprint()多搞几个。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP