免费注册 查看新帖 |

Chinaunix

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

[C] 菜鸟问个栈的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-09-04 10:53 |只看该作者 |倒序浏览
经常会在实际应用中,碰到栈的问题。

1.比如说函数调用,参数是压进栈里的。
    这个栈的地址在哪里,栈的大小是怎么确定的?

2.linux中一些task(thread),也会先分配栈。
   这个栈是用来干嘛的?

3.还有哪些地方用到栈,该怎么理解。
  我总感觉很模糊,不够清晰,不够透彻,有没有什么书推荐的?

谢谢。

论坛徽章:
0
2 [报告]
发表于 2012-09-04 11:15 |只看该作者
栈是系统动态分配的    至于地址  SS:SP指向的是栈顶 ,栈的大小有系统确定  windows 下默认是1MB  linux下倒是不知道多大,如果需要  系统会动态的调整栈的大小
线程也有自己的线程栈   用于存放线程自己的数据  防止多线程中各线程数据相互干扰
栈可以用来存放局部变量   函数参数  保存函数调用现场等等
书嘛   看看汇编吧



论坛徽章:
0
3 [报告]
发表于 2012-09-04 11:22 |只看该作者
回复 2# 1053304571


    那么所有的函数调用,都使用的是同一栈。这个栈就是事先分配好的?

论坛徽章:
0
4 [报告]
发表于 2012-09-04 11:26 |只看该作者
函数调用使用调用他的线程的栈传递参数和保存现场

论坛徽章:
0
5 [报告]
发表于 2012-09-04 16:37 |只看该作者
回复 3# bespecial
linux线程或进程的用户栈地址是一开始运行的时候就定了的,缺省好像最大8M(记得不是很清楚,可以用ulimit调整),感兴趣的看下内核里execve系统调用代码。
动态局部变量,函数参数都在栈上,不理解的话反汇编看下代码。



   

论坛徽章:
0
6 [报告]
发表于 2012-09-04 19:29 |只看该作者
详细给你讲下!
  1. #include<stdio.h>

  2. int a = 100;
  3. int arr[10];
  4. int b;

  5. int add(int a, int b)
  6. {
  7.     int c = a+b;
  8.     return c;
  9. }

  10. int main()
  11. {
  12.     int m = 10;
  13.     int n = 20;
  14.     int val_1 =0;
  15.     int val_2 = 0;

  16.     printf("a=%d\n",m);
  17.     printf("b=%d\n",n);
  18.     for(int i=0; i<10; ++i){
  19.         printf("%d\t",arr[i]);
  20.     }   
  21.     printf("%n");

  22.     val_1 = add(a,b);
  23.     val_2 = add(m,n);

  24.     printf("a+b=%d\n",val_1);
  25.     printf("m+n=%d\n",val_2);
  26.     m = n;
  27.     n = a;
  28.     return 0;
  29. }
复制代码
C程序的存储空间布局有以下几个方面。
1:正文段(Text segment),这里面就是CPU所要执行的程序指令。它有两个特性a:可共享,比如你打开了10个vi编辑器,这十个vi进程在内存里面的正文段只需要一个副本。b:只读,防止程序意外修改其自身指令。像上面这个简单的程序,编译之后变成二进制文件,其正文段就是CPU执行这个程序的所有指令。

2:初始化数据段(Initialized data segment),也称数据段,这里面存储了程序当中明确赋予初值的变量。比如上面程序当中的变量a。

3:未初始化数据段(Uninitialized data segment),也称bss段,存放在这个里面的变量,在程序运行之前内核将此段中的数据初始化为0或者空指针。比如上面程序当中的arr数组和变量b。

4:栈,自动变量变量和每一次函数调用所需要保存的信息都在栈当中。比如上面程序在运行过程中,变量,m.n...,以及在调用add函数时,函数里面的临时变量,以及函数返回的地址,调用者的信息等。注意:递归调用时,函数每调用一次自身,就会使用一个新的栈帧,这样做的好处是同一函数的两个调用实例的变量集不会互相影响。因此在使用递归的时候要注意递归次数。栈的大小有限,ubuntu 12.04上面测试了一下,一个线程栈的大小默认最大为8M,当栈的使用超过这个大小而没有相应处理时,会崩溃。当然这个大小,可以通过ulimit命令或者再程序当中调用相应接口改变(创建线程时可以通过pthread_attr_setstack这一类函数实现,其他方法没有特意去查)。

5:堆,这个应该简单,动态分配内存都会从这里面取。当然这是在new没有被重载,malloc等函数没有被覆盖的情况下。

论坛徽章:
0
7 [报告]
发表于 2012-09-05 10:39 |只看该作者
回复 6# wansbest
谢谢。



   

论坛徽章:
0
8
发表于 2012-09-05 10:40
回复 6# wansbest
谢谢,有点头绪

   

论坛徽章:
0
9 [报告]
发表于 2012-09-05 10:41 |只看该作者
回复 5# janetliu9


    谢谢。我看SDK时,就发现,os只有在创建新的task时,才会划分task的栈。
   有点头绪了。

论坛徽章:
0
10 [报告]
发表于 2012-09-05 17:30 |只看该作者
大伙看看,这个
http://www.cnblogs.com/lknlfy/archive/2012/06/03/2532986.html
我有个疑问:
main函数中,为何要 sub    $0x18,%esp
而test中,sub    $0x10,%esp
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP