Chinaunix首页 | 论坛 | 博客
  • 博客访问: 229527
  • 博文数量: 31
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 296
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-22 11:52
文章分类

全部博文(31)

文章存档

2018年(3)

2017年(11)

2016年(12)

2015年(5)

我的朋友

分类: C/C++

2017-07-07 16:51:31


对于偶发性的段错误,最好能把core文件抓下来,慢慢进行分析,最近写的多线程代码就出现段错误,因此总结一下core 文件相关的内容和gdb 调试的常用命令

1. core 文件的设置
一般情况linux 系统的core文件开关是关闭的,可通过 ulimit –c 查看允许生成的core文件的大小,如果是0,表示不生成core件。 
ulimit –c 数值/ unlimited 可设置core文件允许的最大值,其中unlimited表示不限制,
通过ulimit 命令只能临时生效,重启之后配置失效,可以把命令”ulimit –c unlimited” 添加到/etc/profile 文件,这样重启也能生效

2.core 文件的保存
默认情况下core 文件生成在/ 根目录下,可以通过以下两个来设置core文件的目录和命名规则
(1) /proc/sys/kernel/core_uses_pid ,该参数为1,则core文件以pid作为扩展,否则为0
(2) proc/sys/kernel/core_pattern 可以设置格式化的 core 文件保存位置或文件名,例如:
echo "/corefile/core-%e-%p-%t" > proc/sys/kernel/core_pattern ,则core 文件放到/corefile目录下,文件名格式是core+命令名称+pid+时间戳,以下是各个参数的说明:
%p – pid,在core文件名中添加pid
%u – uid, 在core文件名中添加uid
%g – gid, 在core文件名中添加gid
%s -导致产生 core 的信号, 在core文件名中添加产生core文件的信号
%t - core 文件生成时的 unix 时间, 在core文件名中添加时间戳
%h -主机名, 在core文件名中添加主机名
%e -命令名, 在core文件名中添加产生这个core文件的命令名

3.gdb 的常用命令
gdb executable-file core-file/process-id ,gdb+可执行文件+core文件/进程id,可以调试正在运行的进程或者core 文件
gdb 调试core 文件的时候,frame/f 可以进入到不同的栈,就是bt 显示的各个函数,从最顶层的栈开始,分别是0,1,2….., 进入到不同的函数可以通过p打印各个参数,变量的值

gdb –x cmds:cmds 可以是一个集合了这些命令的文件,如果频繁退出gdb,可以把各种命令放到这个文件,随着gdb 一起运行,就不用频繁重新设置了,比如设置断点,设置fork模式等,这些在gdb内可以运行的命令都可以

set follow-fork-mode child :跑子进程
set follow-fork-mode parent :跑父进程
在代码中有fork 或者popen,这些会产生子进程的地方,可以通过set follow-fork-mode 来选择是进入子进程还是父进程调试

set scheduler-locking on: 禁止多线程切换
set scheduler-locking off: 允许多线程切换,
调试多线程的代码的时候,可以通过这个设置来确保只有当前线程在运行

set detach-on-fork mode on : 调试一个进程
set detach-on-fork mode off :同时调试父子进程

finish:当step 进入了一个函数之后,finish 可以跳出函数
until :until 可以快速跳出循环,until + linenum ,就能跳到第几行

info 命令可以查看各种信息,比如info thread,info break,

thread +线程号,可以切换到指定线程

断点的设置,有各种各样的,也可以进行条件断点设置,具体的可以通过gdb内部的help 查看

4.段错误
常见段错误原因:
(1)访问不存在的内存地址
(2)访问系统保护的内存地址
(3)访问只读的内存地址 
(4)栈溢出

避免段错误,一定要注意以下几点:
指针:定义了指针后记得初始化指针,在使用的时候记得判断是否为NULL,释放的时候是否双重释放了
数组:是否被初始化,数组下标是否越界,数组元素是否存在等。 
在访问变量时,注意变量所占地址空间是否已经被程序释放掉。 
在处理变量时,注意变量的格式控制是否合理

出现段错误,dmesg 或者在/var/log/message 下都会有提示,
nm :可以查看目标文件的所有符号,以及这些符号的属性
ldd :可以查看目标文件所以连接的库
cat /proc/pid/maps:可以查看进程的地址空间,通过定位dmesg 看到的地址,可以知道段错误大概发送在那些代码

总的来说,多线程的代码经常容易出现各种问题,函数注意可重入,全局变量要记得加锁,用到的库也要确保是支持多线程的








阅读(3272) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~