这篇文章主要介绍的就是在产生段错误时如何快速定位到错误的位置?
一.一个简单的关于段错误的实例
对该程序进程编译链接运行之后会产生如下错误:
在上面的错误中可以看到core dumped,那仫什仫是core dumped呢?
二.什仫是core dump?
core的意思是核心,dumped的意思就是抛出,转储,core dumped就是核心转储的意思。当一个进程异常退出前,该进程会抛出当时该程序进程的内存详细情况存储在硬盘上,文件名通常是core,这就叫core dump。
进程异常终止通常是因为代码存在BUG,比如非法内存访问导致段错误,事后可以用调试器检查core文件以查清错误原因,这叫做事后调试。
三.如何使用gdb和core dumped快速定位到错误位置?
一个进程允许产生多大的core文件取决于进程的Resource Limit(这个信息保存 在PCB中)。默认是不允许产生core文件的,因为core文件中可能包含用户密码等敏感信息,不安全。在开发调试阶段可以用ulimit命令改变这个限制,允许产生core文件。
1.core文件是内核生成的,那某一个进程因为段错误而崩溃的时候的内存映像很大,那必然会生成一个很大的core文件,我们可以使用umilit -a显示当前shell下的各种软硬件的上限。
我们也可以通过ulimit命令来设置生成core文件的大小,
例如:(1).ulimit -c unlimited,这里就是设置生成的core文件无大小限制。
(2).ulimit -c [size],表示设置生成的core文件的最大上限为size。
eg1:ulimit -a
eg2:使用ulimit -c 1024修改core文件的最大上限
2.在修改了core文件的上限之后此时再次对该文件进行编译链接运行就会产生一个core.xxx的文件,该文件非常大
3.使用gdb和core dumped调试该文件:gdb 程序名 core.xxx,只要输入gdb signal core.3250即可,在进入gdb之后可以使用where查找出错的位置也可以使用core-file core.xxx来查找错误的位置。
(1).使用core-file core.xxx的形式定位错误
(2).在gdb状态下使用where来定位错误
转载地址:http://blog.csdn.net/oneday_789/article/details/72840850
信号主要是用于不同进程之间进行通信的机制,进程之间的相互协作也正是通过发送信号来完成的,而信号的本质就是修改PCB中关于信号变量的某个比特位(至于为什么是一个比特位,随后就会做出解释)
查看当前系统定义的信号列表:kill -l
请看仔细咯,上面的信号量列表个数并不是64个,而是62个
信号分类
普通信号:1——31号信号
实时信号:34——64号信号
在我们的学习中主要研究的是1——31号普通信号,因此在对应的PCB中采用位图这个数据结构,就可以表示一个信号的存在与否,这也解释了上面的信号量本质为什么是修改PCB中管理信号的变量的一个比特位
背景知识
前台进程:基本上不和用户交互,优先级稍微低一些
后台进程:需要和用户进行交互,需要较高响应速度,优先级别稍微高一些
信号产生的条件
(1)用户在终端按下某些组合键,终端驱动程序会发送信号给前台信号;
(2)硬件异常产生信号,有硬件检测并发送给内核,然后由内核向当前进程发送信号;
进程终止的根本原因就是因为收到信号
(3)使用kill命令发送信号给其他进程;
信号的三种处理方式
(1)忽略此信号(大多数信号都可以使用这种方式处理)
特例:SIGKILL和SIGSTOP
原因:他们向超级用户提供一种使进程终止或停止的可靠方法,同时,如果忽略某些由硬件异常产生的信号,则进程的行为是未定义的。
(2)直接执行进程对于该信号的默认动作(与信号的种类有关,大多数会直接终止该进程)
(3)捕捉信号(执行自定义动作,使用signal函数,而要做到这一点必须调用handler用户函数,可以执行用户希望做的事情)
特例:不能捕捉SIGKILL和SIGSTOP函数
原因:试想一下,如果所有的信号都可以被捕捉,那么当非法用户入侵时就会导致进程永远杀不掉,因此系统在最初设计这些信号时,就特意留出了不能被捕捉的信号。
#include <signal.h>
typedef void (*sighandler_t)(int); //具体执行动作的函数
sighandler_t signal(int signum, sighandler_t handler); //第一个参数,信号编号,第二个参数,信号执行的动作
代码示例:
#include<stdio.h>
#incldue<stdlib.h>
#include<signal.h>
void* mysig(int sig)
{
printf("pid: %d,sig is %d\n",getpid(), sig);
}
int main()
{
signal(2,mysig);
retrurn 0;
}
查看当前的mysignal进程状态
利用core dump(核心转储)定位错误地方
error:error.c
gcc -o error error.c
.PHONY:clean
clean:
rm -f error
#include<stdio.h>
int main()
{
int* p=10;
*p=5;
printf("%d",(int)p);
return 0;
}
运行结果:
先试用ulimit -a来查看当前系统下各种资源的上限
系统默认的大小是0,而core dump的作用是,当一个进程正在运行,突然收到一场错误时,操作系统为了方便调试,将内存中的进程数据存储到硬盘中。但是以死循环的形式将错误不停的存储时,后果可想而知。
修改ulimit -c [size]修改core dump的大小
修改core文件之后,再次编译查看时,就会有一个很大的core文件产生(其后的数字表示进程号)
使用core-file core.xxxx定位错误
转载出处:http://m.blog.csdn.net/article/details?id=72848372