转自:http://blog.csdn.net/sunny04/article/details/46805261

版权声明:本文为博主原创文章,未经博主允许不得转载。

进程是操作系统的最小资源管理单元, 线程是操作系统最小的执行单元。 一个进程可以有多个线程, 也就是说多个线程分享进程的资源,包括栈区,堆区,代码区,数据区等。

[cpp] view plaincopy
  1. sundh@linhaoIPTV:~$ ulimit -a
  2. core file size          (blocks, -c) 0
  3. data seg size           (kbytes, -d) unlimited
  4. scheduling priority             (-e) 0
  5. file size               (blocks, -f) unlimited
  6. pending signals                 (-i) 31675
  7. max locked memory       (kbytes, -l) 64
  8. max memory size         (kbytes, -m) unlimited
  9. open files                      (-n) 1024
  10. pipe size            (512 bytes, -p) 8
  11. POSIX message queues     (bytes, -q) 819200
  12. real-time priority              (-r) 0
  13. stack size              (kbytes, -s) 8192
  14. cpu time               (seconds, -t) unlimited
  15. max user processes              (-u) 31675
  16. virtual memory          (kbytes, -v) unlimited
  17. file locks                      (-x) unlimited

32bit x86机器上面,执行ulimit -a的命令, 可以看到

stack size              (kbytes, -s) 8192    这是否说明在线程中可以分配8M的局部变量(或者说分配7M的局部变量,还有1M的空间存储其他的局部变量或者寄存器状态信息(例如bp等)或者函数压栈信息等)

写代码验证如下:

[cpp] view plaincopy
  1. //test2.cpp
  2. #include <iostream>
  3. #include <string.h>
  4. #include <pthread.h>
  5. #include <stdio.h>
  6. using namespace std;
  7. void* func(void*a)
  8. {
  9. cout << "enter func" << endl;
  10. cout << "enter func" << endl;
  11. int b[1024*1024*2] = {0};
  12. }
  13. int main()
  14. {
  15. int a[1024*1024*3/2]={0};
  16. pthread_t  pthread ;
  17. pthread_create(&pthread, NULL, func, NULL);
  18. cout << "This is a test" << endl;
  19. //pthread_join(pthread, NULL);
  20. return 0;
  21. }

g++ -g -o test2 test2.cpp -lpthread
sundh@linux:~$ gdb test2
GNU gdb (GDB) 7.5-ubuntu
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/sundh/test2...done.
(gdb) r
Starting program: /home/sundh/test2
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1".
[New Thread 0xb7cc1b40 (LWP 10313)]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb7cc1b40 (LWP 10313)]
func (a=0x0) at test2.cpp:10
10          cout << "enter func" << endl;
(gdb)

GDB调试结果如上。   main() 函数中分配1.5M的局部变量,是不会报错的, 但子线程中分配2M的局部变量,就会coredump。 可见,只能分配不大于2M的局部变量,但ulimit -a 查询到的stack size 为8M。

猜想:  线程只能分配不大于 1/4 大小的 stack size 给 局部变量, 这应该是操作系统的规定。(没在网络上面找到相关的文档说明)

那我们现在开始验证我们的猜想:

通过 ulimit -s命令修改默认的栈大小,  下面程序分配5M的局部变量, 也就是说线程栈的大小要 > 20M(5M*4)

[cpp] view plaincopy
  1. //test1.cpp
  2. #include <iostream>
  3. #include <string.h>
  4. #include <pthread.h>
  5. #include <stdio.h>
  6. using namespace std;
  7. void* func(void*a)
  8. {
  9. cout << "enter func" << endl;
  10. cout << "enter func" << endl;
  11. int b[1024*1024*5] = {0};
  12. }
  13. int main()
  14. {
  15. int a[1024*1024*5]={0};
  16. pthread_t  pthread ;
  17. pthread_create(&pthread, NULL, func, NULL);
  18. cout << "This is a test" << endl;
  19. //pthread_join(pthread, NULL);
  20. return 0;
  21. }

ulimit -s 21504 (也就是21M) , 把默认的stack size设置为21M

sundh@linux:~ulimit−s21504sundh@linux: ulimit−s21504sundh@linux:  g++ -g -o test2 test2.cpp -lpthread
sundh@linux:~$ ./test2
This is a testenter func
enter func

可以成功运行, 验证了我们的猜想。

ulimit -s 修改 stack size, 也可以通过 pthread_attr_setstacksize() 来修改。 使用ulimit的一个后果就是它会影响到同一环境(同一shell或者终端)下后续启动的所有程序,如果修改成启动时设置的话就会影响到整个系统。 所以大部分情况下还是使用pthread_attr_setstacksize()

代码如下:

[cpp] view plaincopy
  1. #include <pthread.h>
  2. #include <string.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <unistd.h>
  6. #include <errno.h>
  7. #include <ctype.h>
  8. #define handle_error_en(en, msg) \
  9. do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
  10. #define handle_error(msg) \
  11. do { perror(msg); exit(EXIT_FAILURE); } while (0)
  12. struct thread_info {    /* Used as argument to thread_start() */
  13. pthread_t thread_id;        /* ID returned by pthread_create() */
  14. int       thread_num;       /* Application-defined thread # */
  15. char     *argv_string;      /* From command-line argument */
  16. };
  17. /* Thread start function: display address near top of our stack,
  18. and return upper-cased copy of argv_string */
  19. static void *
  20. thread_start(void *arg)
  21. {
  22. struct thread_info *tinfo = arg;
  23. char *uargv, *p;
  24. <span style="color:#FF0000;">int a[1024*1024*5] = {0};</span>
  25. printf("Thread %d: top of stack near %p; argv_string=%s\n",
  26. tinfo->thread_num, &p, tinfo->argv_string);
  27. uargv = strdup(tinfo->argv_string);
  28. if (uargv == NULL)
  29. handle_error("strdup");
  30. for (p = uargv; *p != '\0'; p++)
  31. *p = toupper(*p);
  32. return uargv;
  33. }
  34. int
  35. main(int argc, char *argv[])
  36. {
  37. int s, tnum, opt, num_threads;
  38. struct thread_info *tinfo;
  39. pthread_attr_t attr;
  40. int stack_size;
  41. void *res;
  42. /* The "-s" option specifies a stack size for our threads */
  43. stack_size = -1;
  44. while ((opt = getopt(argc, argv, "s:")) != -1) {
  45. switch (opt) {
  46. case 's':
  47. stack_size = strtoul(optarg, NULL, 0);
  48. break;
  49. default:
  50. fprintf(stderr, "Usage: %s [-s stack-size] arg...\n",
  51. argv[0]);
  52. exit(EXIT_FAILURE);
  53. }
  54. }
  55. num_threads = argc - optind;
  56. /* Initialize thread creation attributes */
  57. s = pthread_attr_init(&attr);
  58. if (s != 0)
  59. handle_error_en(s, "pthread_attr_init");
  60. if (stack_size > 0) {
  61. s = <span style="color:#FF0000;">pthread_attr_setstacksize</span>(&attr, stack_size);
  62. if (s != 0)
  63. handle_error_en(s, "pthread_attr_setstacksize");
  64. }
  65. /* Allocate memory for pthread_create() arguments */
  66. tinfo = calloc(num_threads, sizeof(struct thread_info));
  67. if (tinfo == NULL)
  68. handle_error("calloc");
  69. /* Create one thread for each command-line argument */
  70. for (tnum = 0; tnum < num_threads; tnum++) {
  71. tinfo[tnum].thread_num = tnum + 1;
  72. tinfo[tnum].argv_string = argv[optind + tnum];
  73. /* The pthread_create() call stores the thread ID into
  74. corresponding element of tinfo[] */
  75. s = pthread_create(&tinfo[tnum].thread_id, &attr,
  76. &thread_start, &tinfo[tnum]);
  77. if (s != 0)
  78. handle_error_en(s, "pthread_create");
  79. }
  80. /* Destroy the thread attributes object, since it is no
  81. longer needed */
  82. s = pthread_attr_destroy(&attr);
  83. if (s != 0)
  84. handle_error_en(s, "pthread_attr_destroy");
  85. /* Now join with each thread, and display its returned value */
  86. for (tnum = 0; tnum < num_threads; tnum++) {
  87. s = pthread_join(tinfo[tnum].thread_id, &res);
  88. if (s != 0)
  89. handle_error_en(s, "pthread_join");
  90. printf("Joined with thread %d; returned value was %s\n",
  91. tinfo[tnum].thread_num, (char *) res);
  92. free(res);      /* Free memory allocated by thread */
  93. }
  94. free(tinfo);
  95. exit(EXIT_SUCCESS);
  96. }

./a.out -s 0x1600000 hola salut servus   (0x1500000  == 20M,0x1600000==21M  )

Thread 1: top of stack near 0xb7d723b8; argv_string=hola

Thread 2: top of stack near 0xb7c713b8; argv_string=salut

Thread 3: top of stack near 0xb7b703b8; argv_string=servus

Joined with thread 1; returned value was HOLA

Joined with thread 2; returned value was SALUT

Joined with thread 3; returned value was SERVUS

程序可以正常运行。 这里需要注意的一点是,主线程还是使用系统默认的stack size,也即8M, 不能在main() 里面声明超过2M的局部变量,创建子线程的时候调用了pthread_attr_setstacksize(), 修改stack size为21M,然后就能在子线程中声明5M的局部变量了。

本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/sky-heaven/p/7654950.html,如需转载请自行联系原作者

thread线程栈size及局部变量最大可分配size【转】相关推荐

  1. 类型,对象,线程栈和托管堆在运行时的相互关系(一)。

    当系统加载一个CLR的进程,进程里面可能有多个线程,这时候系统会给这个进程创建一个大小为1M的线程栈.这个线程栈用来存放方法调用的实参,和方法内部定义的局部变量.下图展示了一个线程栈的栈内存.线程栈的 ...

  2. 【Java 虚拟机原理】线程栈 | 栈帧 | 局部变量表 | 反汇编字节码文件 | Java 虚拟机指令手册 | 程序计数器

    文章目录 一.线程栈 二.栈帧 三.栈帧 - 局部变量表 四.反汇编字节码文件 五.Java 虚拟机指令手册 六.程序计数器 一.线程栈 装载 HelloWorld.class 字节码文件到 Java ...

  3. 栈空间_Linux中的进程栈和线程栈

    1. 进程栈 进程栈是属于用户态栈,和进程虚拟地址空间 (Virtual Address Space) 密切相关.那我们先了解下什么是虚拟地址空间:在 32 位机器下,虚拟地址空间大小为 4G.这些虚 ...

  4. Thread线程从零认识到深层理解——初识

    线程系列目录 Thread线程从零认识到深层理解--初识 Thread线程从零认识到深层理解--六大状态 Thread线程从零认识到深层理解--wait()与notify() Thread线程从零认识 ...

  5. linux存储--进程栈 线程栈 内核栈 中断栈(十六)

    一.栈是什么?栈有什么作用? 首先,栈 (stack) 是一种串列形式的 数据结构.这种数据结构的特点是 后入先出 (LIFO, Last In First Out),数据只能在串列的一端 (称为:栈 ...

  6. 多线程 - 你知道线程栈吗

    问题 1. local 变量的压栈和出栈过程 void func1(){     int a = 0;     int b = 0; } 系统中有一个栈顶指针,每次分配和回收local 变量时,其实就 ...

  7. Linux 中的各种栈:进程栈 线程栈 内核栈 中断栈

    栈是什么?栈有什么作用? 首先,栈 (stack) 是一种串列形式的 数据结构.这种数据结构的特点是 后入先出 (LIFO, Last In First Out),数据只能在串列的一端 (称为:栈顶 ...

  8. 一文读懂 | Linux 中的各种栈:进程栈 线程栈 内核栈 中断栈

    点击蓝字 关注我们 因公众号更改推送规则,请点"在看"并加"星标"第一时间获取精彩技术分享 来源于网络,侵删 栈是什么?栈有什么作用? 首先,栈 (stack) ...

  9. Linux中的各种栈:进程栈 线程栈 内核栈 中断栈

    Linux中的各种栈:进程栈 线程栈 内核栈 中断栈 栈的作用 1. 函数调用 2. 多任务支持 Linux 中有几种栈?各种栈的内存位置? 1. 进程栈 2. 线程栈 3. 进程内核栈 4. 中断栈 ...

最新文章

  1. “不会Linux,怎么干程序员?”骨灰级工程师:干啥都不行!
  2. 机器学习开发的灵药:Docker容器
  3. python对象一定要删除引用吗_在Python中删除一个对象和所有对它的引用?
  4. 找ipcore的地方
  5. 为什么重复值高的字段不能建索引(比如性别字段等)
  6. 统计学习方法之机器学习相关理论
  7. java强引用、软引用、弱引用、虚引用-Java的引用类型总共有四种,你都知道吗
  8. 利用ES6的Generator语法实现自定义iterator
  9. Sql自动更新不同IP的数据库数据。(link Server)
  10. android string 去掉斜杠,Android – PATH中的改装和斜杠字符
  11. 9-5:C++多态之多态和继承的经典题目以及面试中常考内容
  12. seafile安装教程 Linux,CentOS7安装seafile开源版
  13. Android录音采样率限制问题(十一)
  14. javaweb项目静态资源被拦截的解决方法
  15. 关于String内存分配的深入探讨
  16. 想将有色彩的视频进行去色处理就这样做
  17. 【Unity3D读取数据】(三)Xml文件操作(创建、读取、写入、修改)
  18. A题 血管机器人的订购与生物学习#2022年五一数学建模
  19. 模拟电子技术基础 第二章 常用半导体器件原理
  20. 微信小程序tabBar创建

热门文章

  1. asp.net导出Excel类库
  2. Unity 动画属性
  3. POJ 1308 Is It A Tree? (并查集)
  4. HDU5697 刷题计划 dp+最小乘积生成树
  5. presentViewController和pushViewController
  6. 利用协议代理实现导航控制器UINavigationController视图之间的正向传值和反向传值...
  7. CSS3动画@keyframes中translate和scale混用出错问题
  8. query上传插件uploadify参数详细分析
  9. (原创)RHEL/CentOS 5.x使用yum快速安装MySQL 5.5.x
  10. 删除隐藏版本信息 版本回退_git之版本穿梭术