代码编译运行环境:Ubuntu 64bits+g++(-g -m64),其中 -g 表示生成调试版本,-m64 表示生成 64bits 程序。
1.错误代码
先贴出出错的核心代码:
struct GPU_task_head head;//局部栈空间上的变量
cout<<"sizeof(GPU_task_head):"<<sizeof(GPU_task_head)<<endl;
memset(&head,0,sizeof(GPU_task_head));//运行时出错
以上代码会出现segmentation fault(core dumped),本以为是memset数组越界,导致的段错误,经过仔细检查并不是memset越界导致的。那为什么呢?
先看一下错误代码的输出:
再看一下ulimit -a
命令列出的系统对shell 启动进程所占用的资源限制,列出结果如下:
看图片标红的位置,再对比错误代码的输出的结果中变量的大小,你是否发现了什么!
2.ulimit 命令简介
你是否曾遇到过在程序里面创建线程提示你资源不够,你是否曾遇到过在gcc 中加入 -g 选项,程序崩溃时却没有任何 core 文件产生。如果就,那你就要注意到ulimit命令了。
本次错误也是由于系统对进程资源的限制导致了以上的奇怪的错误结果。memset 栈空间出现段错误是由于系统分每个进程分配的空间不足导致的。
ulimit 通过一些参数选项来管理不同种类的系统资源。这里,我们将讲解这些参数的使用。
ulimit 命令的格式为:ulimit [ options ] [limit]
具体的 options 含义以及简单示例可以参考以下表格。
命令选项 | 含义 | 例子 |
---|---|---|
-a | 查看全部资源的使用情况 | ulimit -a 查看全部资源的使用情况 |
-H | 设置硬资源描述限制,一旦设置,不能更改 | ulimit – Hs 64;限制硬资源,线程栈大小为 64K |
-S | 设置软资源限制,一旦设置,可以增加,但是不能超过软资源的限制 | ulimit – Sn 32;限制软资源,32 个文件描述符。 |
-c | core文件最大大小,以blocks为单位 | 一般常用ulimit -c unlimited,设置为不限大小 |
-d | 设置进程最大数据段的大小,以kbytes为单位 | ulimit -d unlimited;对进程的数据段大小不进行限制 |
-f | 设置进程最大可以创建的文件大小,以blocks为单位 | ulimit – f 2048;限制进程可以创建的最大文件大小为 2048 blocks |
-l | 最大可加锁内存大小,以 Kbytes 为单位 | ulimit -l 32;限制最大可加锁内存大小为 32 Kbytes |
-m | 最大内存大小,以 Kbytes 为单位 | ulimit – m unlimited;对最大内存不进行限制 |
-n | 可以打开最大文件描述符的数量 | ulimit –n128;限制最大可以使用 128 个文件描述符 |
-p | 管道缓冲区的大小,以 Kbytes 为单位 | ulimit – p 512;限制管道缓冲区的大小为 512 Kbytes |
-s | 线程栈大小,以 Kbytes 为单位 | ulimit – s 512;限制线程栈的大小为 512 Kbyte |
-t | 最大的 CPU 占用时间,以秒为单位 | ulimit -t unlimited;对最大的 CPU 占用时间不进行限制 |
-u | 用户最大可用的进程数 | ulimit – u 64;限制用户最多可以使用 64 个进程 |
-v | 进程最大可用的虚拟内存,以 Kbytes 为单位 | ulimit -v 200000;限制最大可用的虚拟内存为 200000 Kbytes |
3.错误解决办法
错误代码中局部变量 head 的大小占用了 8.7M 的栈空间,已经超过了系统对 Shell 进程栈空间的限制。虽然在定义时没有报错,但是进行memset 置空值却出现了段错误。因此,我们做如下修改:
ulimit – s 81920
将栈空间改为 81M,这样再运行源程序,顺利通过,问题解决。