pthread之线程堆栈分配不足coredump分析

合集下载

pthread之线程堆栈分配不足coredump分析

pthread之线程堆栈分配不足coredump分析

先来讲说线程内存相关的东西,主要有下面几条:1.进程中的所有的线程共享相同的地址空间。

2.任何声明为static/extern的变量或者堆变量可以被进程内所有的线程读写。

3.一个线程真正拥有的唯一私有储存是处理器寄存器。

4.线程栈可以通过暴露栈地址的方式与其它线程进行共享。

有大数据量处理的应用中,有时我们有必要在栈空间分配一个大的内存块或者要分配很多小的内存块,但是线程的栈空间的最大值在线程创建的时候就已经定下来了,如果栈的大小超过个了个值,系统将访问未授权的内存块,毫无疑问,再来的肯定是一个段错误。

可是没办法,你还是不得不分配这些内存,于是你开会为分配一个整数值而动用malloc这种超级耗时的操作。

当然,在你的需求可以评估的情况下,你的需求还是可以通过修改线程的栈空间的大小来改变的。

下面的我们用pthread_attr_getstacksize和pthread_attr_setstacksize的方法来查看和设置线程的栈空间。

注意:下面的测试代码在我自己的机子上(ubuntu6.06,ubuntu6.10,redhat 9, gentoo)通过了测试,但是很奇怪的是在我同事的机子上,无论是改变环境,还是想其它方法都不能正常的运行。

在网上查了一下,很多人也存在同样的问题,至今不知道为何。

linux线程的实现方式决定了对进程的限制同样加在了线程身上:)所以,有问题,请参见<pthread之线程栈空间(2)(进行栈)直接看代码吧,只有一个C文件(thread_attr.c)#include <limits.h>#include <pthread.h>#include "errors.h"//线程体,在栈中分配一个大小为15M的空间,并进行读写void *thread_routine (void *arg){printf ("The thread is here\n");//栈大小为16M,如果直接分配16M的栈空间,会出现段错误,因为栈中还有其它的//变量要放署char p[1024*1024*15];int i=1024*1024*15;//确定内存分配的确成功了while(i--){p[i] = 3;}printf( "Get 15M Memory\n" );//分配更多的内存(如果分配1024*1020*512的话就会出现段错误) char p2[ 1024 * 1020 + 256 ];memset( p2, 0, sizeof( char ) * ( 1024 * 1020 + 256 ) );printf( "Get More Memory\n" );return NULL;}int main (int argc, char *argv[]){pthread_t thread_id;pthread_attr_t thread_attr;size_t stack_size;int status;status = pthread_attr_init (&thread_attr);if (status != 0)err_abort (status, "Create attr");status = pthread_attr_setdetachstate (&thread_attr, PTHREAD_CREATE_DETACHED);if (status != 0)err_abort (status, "Set detach");//通常出现的问题之一,下面的宏没有定义#ifdef _POSIX_THREAD_ATTR_STACKSIZE//得到当前的线程栈大小status = pthread_attr_getstacksize (&thread_attr, &stack_size); if (status != 0)err_abort (status, "Get stack size");printf ("Default stack size is %u; minimum is %u\n",stack_size, PTHREAD_STACK_MIN);//设置当前的线程的大小status = pthread_attr_setstacksize (&thread_attr, PTHREAD_STACK_MIN*1024);if (status != 0)err_abort (status, "Set stack size");//得到当前的线程栈的大小status = pthread_attr_getstacksize (&thread_attr, &stack_size);if (status != 0)err_abort (status, "Get stack size");printf ("Default stack size is %u; minimum is %u\n",stack_size, PTHREAD_STACK_MIN);#endifint i = 5;//分配5个具有上面的属性的线程体while(i--){status = pthread_create (&thread_id, &thread_attr, thread_routine, NULL); if (status != 0)err_abort (status, "Create thread");}getchar();printf ("Main exiting\n");pthread_exit (NULL);return 0;}看看执行过程:dongq@DongQ_Lap ~/workspace/test/pthread_attr $ makecc -pthread -g -DDEBUG -lrt -o thread_attr thread_attr.cdongq@DongQ_Lap ~/workspace/test/pthread_attr $ ./thread_attrDefault stack size is 8388608; minimum is 16384 //默认的栈大小为8MDefault stack size is 16777216; minimum is 16384 //设置后的结果为16MThe thread is hereThe thread is hereThe thread is hereThe thread is hereThe thread is hereGet 15M MemoryGet More MemoryGet 15M MemoryGet More MemoryGet 15M MemoryGet 15M MemoryGet More MemoryGet More MemoryGet 15M MemoryGet More MemoryMain exitings用下面的命令来看linux下面的对系统的一些限制:dongq@DongQ_Lap ~/workspace/test/pthread_attr $ ulimit -acore file size (blocks, -c) 0data seg size (kbytes, -d) unlimitedscheduling priority (-e) 0file size (blocks, -f) unlimitedpending signals (-i) 16365max locked memory (kbytes, -l) 32max memory size (kbytes, -m) unlimitedopen files (-n) 1024pipe size (512 bytes, -p) 8POSIX message queues (bytes, -q) 819200real-time priority (-r) 0stack size (kbytes, -s) 8196cpu time (seconds, -t) unlimitedmax user processes (-u) 16365virtual memory (kbytes, -v) unlimitedfile locks (-x) unlimited通过上面的命令,我们可以清楚的看到一个进程在正常的情况下,最大的栈空间为8M。

CoreDump分析(精品)

CoreDump分析(精品)

Core dump 基本知识本节主要探讨 core dump 产生的背景知识。

对这部分不感兴趣的读者可以直接阅读第二章,了解基本的 core dump 定位手段。

起源软件是人思维的产物。

智者千虑,必有一失,人的思维总有缺陷,反映到软件层面上就是程序 bug。

程序 bug 的终极体现就是 core dump,core dump 是软件错误无法恢复的产物。

生成过程进程 core dump 与系统 dump 的产生,从程序原理上来说是基本一致的。

dump 的生成一般是在系统进行中断处理时进行的,下面简单介绍一下中断机制。

操作系统的中断机制操作系统是由中断驱动的。

广义的中断一般分为两类,中断 (Interrupts) 和异常(Exceptions)。

中断可在任何时候发生,与 CPU 正在执行什么指令无关,中断主要由 I/O 设备、处理器时钟(分时系统依赖时钟中断划分时间片)或定时器等硬件引发,可以被允许或取消。

而异常是由于 CPU 执行了某些指令引起的,可以包括存储器存取违规、除 0 或者特定调试指令等,内核也将系统服务视为异常。

系统对这两类中断的处理基本上是相同的。

每个中断都会唯一对应到一个中断处理程序,在该中断触发时,相应的处理程序就会被执行。

例如应用进程进行系统调用时,就会触发一个软件异常,进入中断处理函数,完成从用户态到系统态的迁移并进入相应系统调用的入口点。

应用进程 coredump 也是一个类似的过程。

应用进程 core dump 生成过程在进程运行出现异常行为时,例如无效地址访问、浮点异常、指令异常等,将导致系统转入内核态进行异常处理(即中断处理),向相应的进程发出特定信号例如 SIGSEGV、SIGFPE、SIGILL 等。

如果应用进程注册了相应信号的处理函数(例如可通过 sigaction 注册信号处理函数),则调用相应处理函数进行处理(应用程序可以选择记录信息后生成 core dump 并退出);否则将采取默认动作,例如 SIGSEGV 的默认动作是生成 core dump 并退出程序。

关于core_uses_pid标志对多线程程序无用的调查

关于core_uses_pid标志对多线程程序无用的调查

关于core_uses_pid标志对多线程程序无用的调查一、案例的起因与思考在工作的过程中,发现在RHEL5.6系统下,运行进程,一旦应用线程,出core后,总会带着进程ID。

即使在系统中设置core_uses_pid=0,也是不行的。

二、资料的查询与分析在网上“https://”发现了这个bug的存在,简要信息如下:Bug 6312 - core_uses_pid=0 not always honoredStatus: REJECTEDWILL_NOT_FIXReported: 2006-03-30 15:10 byDavid M. LeeProduct: Other Modified: 2007-01-31 01:03(History)Component: Other KernelVersion:2.6.15.2Version: 2.5 Tree: Mainline Platform: i386 Linux Regression: --- Importance: P2 normalAssigned To: other_other@ker nel-bugs.osdl.o rgURL:Depends on:Blocks:Showdependencytree / graph详细信息参见:https:///show_bug.cgi?id=6312从该信息中获知,产生core文件时,名字是由函数format_corename来执行的。

所以,针对内核源码“linux-2.6.27.62 和linux-3.2.7”做了分析。

发现在3.2.7版本的内核中修复了改BUG。

经过对该函数的分析,发现我们之所以出现问题,就是由于参数nr_threads引起的,而这个参数的含义就是使用该资源的线程个数,该值是被内敛函数“zap_threads”来设置的。

而这段代码基本上是不可避免的都要走到的。

我们如何跳过这段代码呢?如何让nr_threads 不起作用呢?/* Backward compatibility with core_uses_pid:** If core_pattern does not include a %p (as is the default)* and core_uses_pid is set, then .%pid will be appended to* the filename. Do not do this for piped commands. */if (!ispipe && !pid_in_pattern&& (core_uses_pid || nr_threads)) {rc = snprintf(out_ptr, out_end - out_ptr,".%d", task_tgid_vnr(current));if (rc > out_end - out_ptr)goto out;out_ptr += rc;}Fork为何会遵循core_uses_pid的设置呢?参见zap_threads中的解释。

C++ Core dump问题定位方法

C++ Core dump问题定位方法
WaitForSingleObject(thread1, INFINITE);
return 0; }
该程序分别启动两个线程,线程 1 和线程 2 由于都在等待对方设置信号量为 FLASE,后退出线程,互相等待导致死锁。
这时抓取 Core dump 的方法跟上面提到的一样,不同的是,这时只需要抓 取内存的快照,不需要一开始就运行 adplus,只要在发现有线程死锁现象时运 行 adplus,并把-crash 参数改为-hang,即可。
2、 何谓 Core dump 我们在开发(或使用)一个程序时,最怕的就是程序莫明其妙地当掉。虽然
系统没事,但我们下次仍可能遇到相同的问题。于是这时操作系统就会把程序当 掉时的内存内容 dump 出来(现在通常是写在一个叫 core 的文件里面,不同 操作系统下的名称可能不同),让我们或是调试器做为参考,进行问题定位。这 个动作就叫作 Core dump。
3、 为何会发生 Core dump 前面说过,在程序当掉时出错。C/C++语言中,最常发生错误的地方就是
指针有问题。您可以利用 core 文件和调试器把错误找出来。
4、 Core dump 适用范围 Core dump 适用于定位 C++程序内存错误、线程死锁等复杂问题,特别是
当程序在用户机子上出现内存问题时,通过日志一般也很难定位出来(由于程序 当了,写日志的线程也跟着程序结束了,错误信息很可能没有写到日志里),这 种情况只有通过获取当时的 Core dump 文件来定位,没有第二种方法了。
命令解释如下: 参数 crash:用于捕获 Coredump; pn:用于指定所需监视的进程名称; o(小写字母):用于指示所捕获 Core dump 文件输出目录; 由于 Core dump 写入的是出现问题时内存的信息,因此输出的 dump 文 件可能会比较大从几 M 到几 G 不定,根据当时出现问题的具体情况,因此在指 定 Core dump 输出目录时,最好指定在空间比较大的磁盘下。当执行 adplus 后,在“o”参数指定的路径下,可以看到多了一个目录,一般目录名称为:” Crash_Mode__Date_01-18-2010__Time_18-49-4343”,即 Crash 开头,后接 Core dump 产生的日期、时间。里面会有“ADPlus_report.txt”、“PID-3324__ DGISPOWERMODEL.EXE__Date_01-18-2010__Time_19-11-2424.log ” 、 “Process_List.txt”三个文件,记录了程序运行时的进程信息等,可以用记事本 打开查看。 当发生 Core dump 后,这个目录下就会多三个以“.dmp”为后缀名的文 件文件(一般是三个,有时也可能只有一个)。三个文件一般两个里面有包含 “1st”、一个包含“2nd”的字样,这个是跟 windows 系统异常捕获机制分为 两阶段处理有关,具体可以 Google 下,不具体解释。这三个文件就是 Core

段错误(core dumped)

段错误(core dumped)

段错误 (core dumped)当我们的程序崩溃时,内核有可能把该程序当前内存映射到core文件里,方便程序员找到程序出现问题的地方。

最常出现的,几乎所有C程序员都出现过的错误就是“段错误”了。

也是最难查出问题原因的一个错误。

下面我们就针对“段错误”来分析core文件的产生、以及我们如何利用core文件找到出现崩溃的地方。

何谓core文件当一个程序崩溃时,在进程当前工作目录的core文件中复制了该进程的存储图像。

core文件仅仅是一个内存映象(同时加上调试信息),主要是用来调试的。

使用core文件调试程序看下面的例子:#includechar *str = "test";void core_test(){str[1] ='T';}int main(){core_test();return0;}编译:gcc –g core_dump_test.c -o core_dump_test如果需要调试程序的话,使用gcc编译时加上-g选项,这样调试core文件的时候比较容易找到错误的地方。

执行:./core_dump_test段错误运行core_dump_test程序出现了“段错误”,但没有产生core文件。

这是因为系统默认core文件的大小为0,所以没有创建。

可以用ulimit命令查看和修改core文件的大小。

ulimit -c 0ulimit -c 1000ulimit -c 1000-c指定修改core文件的大小,1000指定了core文件大小。

也可以对core文件的大小不做限制,如:ulimit -c unlimitedulimit -c unlimited如果想让修改永久生效,则需要修改配置文件,如.bash_profile、/etc/profile或/etc/security/limits.conf。

再次执行:./core_dump_test段错误 (core dumped)ls core.*core.6133可以看到已经创建了一个core.6133的文件.6133是core_dump_test程序运行的进程ID。

Linux内核调试方法总结之coredump

Linux内核调试方法总结之coredump

Linux内核调试方法总结之coredump什么是core dump?分析core dump是Linux应用程序调试的一种有效方式,像内核调试抓取ram dump一样,core dump主要是获取应用程序崩溃时的现场信息,如程序运行时的内存、寄存器状态、堆栈指针、内存管理信息、函数调用堆栈信息等。

Core dump又称为“核心转储”,是Linux基于信号实现的。

Linux中信号是一种异步事件处理机制,每种信号都对应有默认的异常处理操作,默认操作包括忽略该信号(Ignore)、暂停进程(Stop)、终止进程(T erminate)、终止并产生core dump(Core)等。

Signal Value Action CommentSIGHUP 1 Term Hangup detected on controlling terminal or death of controlling processSIGINT 2 Term Interrupt from keyboard SIGQUIT 3 Core Quit from keyboardSIGILL4Core Illegal InstructionSIGTRAP5Core Trace/breakpoint trapSIGABRT6Core Abort signal from abort(3) SIGIOT 6 Core IOT trap. A synonym for SIGABRT SIGEMT 7 TermSIGFPE8Core Floating point exceptionSIGKILL 9 Term Kill signal, cannot be caught, blocked or ignored.SIGBUS10,7,10Core Bus error (bad memory access)SIGSEGV11Core Invalid memory referenceSIGPIPE 13 Term Broken pipe: write to pipe with no readers SIGALRM 14 Term Timer signal from alarm(2)SIGTERM 15 Term Termination signalSIGUSR1 30,10,16 Term User-defined signal 1SIGUSR2 31,12,17 Term User-defined signal 2SIGCHLD 20,17,18 Ign Child stopped or terminatedSIGCONT 19,18,25 Cont Continue if stoppedSIGSTOP 17,19,23 Stop Stop process, cannot be caught, blocked or ignored.SIGTSTP 18,20,24 Stop Stop typed at terminalSIGTTIN 21,21,26 Stop Terminal input for background process SIGTTOU 22,22,27 Stop Terminal output for background process SIGIO 23,29,22 Term I/O now possible (4.2BSD)SIGPOLL Term Pollable event (Sys V). Synonym for SIGIO SIGPROF 27,27,29 Term Profiling timer expiredSIGSYS12,31,12Core Bad argument to routine (SVr4)SIGURG 16,23,21 Ign Urgent condition on socket (4.2BSD) SIGVTALRM 26,26,28 Term Virtual alarm clock (4.2BSD)SIGXCPU24,24,30Core CPU time limit exceeded (4.2BSD) SIGXFSZ25,25,31Core File size limit exceeded (4.2BSD) SIGSTKFLT 16 Term Stack fault on coprocessor (unused) SIGCLD 18 Ign A synonym for SIGCHLDSIGPWR 29,30,19 Term Power failure (System V)SIGINFO 29 A synonym for SIGPWR, on an alpha SIGLOST 29 Term File lock lost (unused), on a sparc SIGWINCH 28,28,20 Ign Window resize signal (4.3BSD, Sun) SIGUNUSED 31 Core Synonymous with SIGSYS什么情况下会产生core dump呢?以下情况会出现应用程序崩溃导致产生core dump:1.内存访问越界(数组越界、字符串无\n结束符、字符串读写越界)2.多线程程序中使用了线程不安全的函数,如不可重入函数3.多线程读写的数据未加锁保护(临界区资源需要互斥访问)4.非法指针(如空指针异常或者非法地址访问)5.堆栈溢出怎么获取core dump呢?Linux提供了一组命令来配置core dump行为:1. ulimit –c 查看core dump机制是否使能,若为0则默认不产生core dump,可以使用ulimit –c unlimited使能core dump2. cat /proc/sys/kernel/core_pattern 查看core文件默认保存路径,默认情况下是保存在应用程序当前目录下,但是如果应用程序中调用chdir()函数切换了当前工作目录,则会保存在对应的工作目录3. echo “/data/xxx/<core_file>” > /proc/sys/kernel/core_pattern 指定core文件保存路径和文件名,其中core_file可以使用以下通配符:%% 单个%字符%p 所dump进程的进程ID%u 所dump进程的实际用户ID%g 所dump进程的实际组ID%s 导致本次core dump的信号%t core dump的时间 (由1970年1月1日计起的秒数)%h 主机名%e 程序文件名4. ulimit –c [size] 指定core文件大小,默认是不限制大小的,如果自定义的话,size值必须大于4,单位是block(1block = 512bytes)怎么分析core dump?我们首先编写一个程序,人为地产生core dump并获取core dump文件。

gdb调试coredump文件过程:

gdb调试coredump文件过程:

gdb coredump应用程序 coredump文件 调试coredump文件
通过以上三步就可以调试coredump文件了 通过以下命令调试coredump文件 info threads 显示所有线程 bt 显示线程堆栈信息 thread thread_num 切换线程 frame num 切换栈 info r 显示当前帧的寄存器信息 (每一帧的寄存器信息都是不相同的)
readelf应用coredump readelf -h 读取coredump文件头 readelf -wl 读取应用程序debug_line readelf -源自f 读取应用程序fde和cie信息
博客园 用户登录 代码改变世界 密码登录 短信登录 忘记登录用户名 忘记密码 记住我 登录 第三方登录/注册 没有账户, 立即注册
gdb调试 coredump文件过程:
第一步:首先需要一个进程的 coredump文件,怎么搞出 coredump文 件 呢 ?
1、 ps -fax|grep
进程名称 找到进程的pid
2、gdb -p pid
调试进程
3、gcore coredump名称 则生成core文件
第二步:找出coredump文件的应用程序
1、gdb -c corefile 使用gdb调试core文件
2、info auxv
索引31对应的是core文件的应用程序
第三部:gdb使用应用程序调试coredump文件

CoreDump详解

CoreDump详解

CoreDump详解1. 什么是Core:Sam之前一直以为Core Dump中Core是Linux Kernel的意思. 今天才发现在这里,Core是另一种意思:在使用半导体作为内存的材料前,人类是利用线圈当作内存的材料(发明者为王安),线圈就叫作core ,用线圈做的内存就叫作core memory。

如今,半导体工业澎勃发展,已经没有人用core memory 了,不过,在许多情况下,人们还是把记忆体叫作core 。

2. 什么是Core Dump:我们在开发(或使用)一个程序时,最怕的就是程序莫明其妙地当掉。

虽然系统没事,但我们下次仍可能遇到相同的问题。

于是这时操作系统就会把程序当掉时的内存内容dump 出来(现在通常是写在一个叫core 的file 里面),让我们或是debugger 做为参考。

这个动作就叫作core dump。

3. Core Dump时会生成何种文件:Core Dump时,会生成诸如core.进程号的文件。

4. 为何有时程序Down了,却没生成Core文件。

Linux下,有一些设置,标明了resources available to the shell and to processes。

可以使用#ulimit -a来看这些设置。

(ulimit是bash built-in Command)-a All current limits are reported-c The maximum size of core files created-d The maximum size of a process鈥檚data segment-e The maximum scheduling priority ("nice")-f The maximum size of files written by the shell and its children-i The maximum number of pending signals-l The maximum size that may be locked into memory-m The maximum resident set size (has no effect on Linux)-n The maximum number of open file descriptors (most systems do not allow this value to be set)-p The pipe size in 512-byte blocks (this may not be set)-q The maximum number of bytes in POSIX message queues -r The maximum real-time scheduling priority-s The maximum stack size-t The maximum amount of cpu time in seconds-u The maximum number of processes available to a single user-v The maximum amount of virtual memory available to the shell-x The maximum number of file locks从这里可以看出,如果-c是显示:core file size (blocks, -c)如果这个值为0,则无法生成core文件。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

先来讲说线程内存相关的东西,主要有下面几条:1.进程中的所有的线程共享相同的地址空间。

2.任何声明为static/extern的变量或者堆变量可以被进程内所有的线程读写。

3.一个线程真正拥有的唯一私有储存是处理器寄存器。

4.线程栈可以通过暴露栈地址的方式与其它线程进行共享。

有大数据量处理的应用中,有时我们有必要在栈空间分配一个大的内存块或者要分配很多小的内存块,但是线程的栈空间的最大值在线程创建的时候就已经定下来了,如果栈的大小超过个了个值,系统将访问未授权的内存块,毫无疑问,再来的肯定是一个段错误。

可是没办法,你还是不得不分配这些内存,于是你开会为分配一个整数值而动用malloc这种超级耗时的操作。

当然,在你的需求可以评估的情况下,你的需求还是可以通过修改线程的栈空间的大小来改变的。

下面的我们用pthread_attr_getstacksize和pthread_attr_setstacksize的方法来查看和设置线程的栈空间。

注意:下面的测试代码在我自己的机子上(ubuntu6.06,ubuntu6.10,redhat 9, gentoo)通过了测试,但是很奇怪的是在我同事的机子上,无论是改变环境,还是想其它方法都不能正常的运行。

在网上查了一下,很多人也存在同样的问题,至今不知道为何。

linux线程的实现方式决定了对进程的限制同样加在了线程身上:)所以,有问题,请参见<pthread之线程栈空间(2)(进行栈)直接看代码吧,只有一个C文件(thread_attr.c)#include <limits.h>#include <pthread.h>#include "errors.h"//线程体,在栈中分配一个大小为15M的空间,并进行读写void *thread_routine (void *arg){printf ("The thread is here\n");//栈大小为16M,如果直接分配16M的栈空间,会出现段错误,因为栈中还有其它的//变量要放署char p[1024*1024*15];int i=1024*1024*15;//确定内存分配的确成功了while(i--){p[i] = 3;}printf( "Get 15M Memory!!!\n" );//分配更多的内存(如果分配1024*1020*512的话就会出现段错误) char p2[ 1024 * 1020 + 256 ];memset( p2, 0, sizeof( char ) * ( 1024 * 1020 + 256 ) );printf( "Get More Memory!!!\n" );return NULL;}int main (int argc, char *argv[]){pthread_t thread_id;pthread_attr_t thread_attr;size_t stack_size;int status;status = pthread_attr_init (&thread_attr);if (status != 0)err_abort (status, "Create attr");status = pthread_attr_setdetachstate (&thread_attr, PTHREAD_CREATE_DETACHED);if (status != 0)err_abort (status, "Set detach");//通常出现的问题之一,下面的宏没有定义#ifdef _POSIX_THREAD_ATTR_STACKSIZE//得到当前的线程栈大小status = pthread_attr_getstacksize (&thread_attr, &stack_size); if (status != 0)err_abort (status, "Get stack size");printf ("Default stack size is %u; minimum is %u\n",stack_size, PTHREAD_STACK_MIN);//设置当前的线程的大小status = pthread_attr_setstacksize (&thread_attr, PTHREAD_STACK_MIN*1024);if (status != 0)err_abort (status, "Set stack size");//得到当前的线程栈的大小status = pthread_attr_getstacksize (&thread_attr, &stack_size);if (status != 0)err_abort (status, "Get stack size");printf ("Default stack size is %u; minimum is %u\n",stack_size, PTHREAD_STACK_MIN);#endifint i = 5;//分配5个具有上面的属性的线程体while(i--){status = pthread_create (&thread_id, &thread_attr, thread_routine, NULL); if (status != 0)err_abort (status, "Create thread");}getchar();printf ("Main exiting\n");pthread_exit (NULL);return 0;}看看执行过程:dongq@DongQ_Lap ~/workspace/test/pthread_attr $ makecc -pthread -g -DDEBUG -lrt -o thread_attr thread_attr.cdongq@DongQ_Lap ~/workspace/test/pthread_attr $ ./thread_attrDefault stack size is 8388608; minimum is 16384 //默认的栈大小为8MDefault stack size is 16777216; minimum is 16384 //设置后的结果为16MThe thread is hereThe thread is hereThe thread is hereThe thread is hereThe thread is hereGet 15M Memory!!!Get More Memory!!!Get 15M Memory!!!Get More Memory!!!Get 15M Memory!!!Get 15M Memory!!!Get More Memory!!!Get More Memory!!!Get 15M Memory!!!Get More Memory!!!Main exitings用下面的命令来看linux下面的对系统的一些限制:dongq@DongQ_Lap ~/workspace/test/pthread_attr $ ulimit -acore file size (blocks, -c) 0data seg size (kbytes, -d) unlimitedscheduling priority (-e) 0file size (blocks, -f) unlimitedpending signals (-i) 16365max locked memory (kbytes, -l) 32max memory size (kbytes, -m) unlimitedopen files (-n) 1024pipe size (512 bytes, -p) 8POSIX message queues (bytes, -q) 819200real-time priority (-r) 0stack size (kbytes, -s) 8196cpu time (seconds, -t) unlimitedmax user processes (-u) 16365virtual memory (kbytes, -v) unlimitedfile locks (-x) unlimited通过上面的命令,我们可以清楚的看到一个进程在正常的情况下,最大的栈空间为8M。

那么8M我们够用吗?当你分配大量的static或者auto变量的时候,一般都是放在栈空间的。

如果分配一个大于8M的数组,会发生什么呢?先来看看测试代码:int main(){int i = 1024 * 1024 * 8;char p[ i ];memset( p, 0, sizeof( char ) * i );while( i-- ){p[ i ] = i;}return 0;}上面的代码直接分配一个大小为8M的数组,编译后运行,出现段错误!!很奇怪吗?不是说可以分配8M吗?怎么不行?当然不行,因为在分配p时,栈中已经放有其它的变量,最明显的就是int i;这样子的话,栈中就没有足够的空间给变量p分配,从而出现段错误。

下面用gdb进行调试:DongQ_Lap pthread_attr # gdb process_stackGNU gdb 6.5(gdb) b mainBreakpoint 1 at 0x8048392: file process_stack.c, line 13.(gdb) r > /home/dongq/tmp/gdb.txtStarting program:/home/dongq/workspace/test/pthread_attr/process_stack >/home/dongq/tmp/gdb.txt[Thread debugging using libthread_db enabled][New Thread -1209533760 (LWP 10947)][Switching to Thread -1209533760 (LWP 10947)]Breakpoint 1, main () at process_stack.c:1313 {(gdb) s15 int i = 1024 * 1024 * 8;(gdb) s16 char p[ i ];(gdb) s17 memset( p, 0, sizeof( char ) * i );(gdb) p p$1 = 0xbf6c3470 <Address 0xbf6c3470 out of bounds>(gdb) sProgram received signal SIGSEGV, Segmentation fault.0x080483d4 in main () at process_stack.c:1717 memset( p, 0, sizeof( char ) * i );(gdb) bt#0 0x080483d4 in main () at process_stack.c:17(gdb) quit看到了吗?char p[i]这句执行后的结果是out of bounds!!也就是内存没有分配成功。

相关文档
最新文档