Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1307654
  • 博文数量: 254
  • 博客积分: 1586
  • 博客等级: 上尉
  • 技术积分: 2295
  • 用 户 组: 普通用户
  • 注册时间: 2009-01-15 16:38
个人简介

linux学习中

文章分类

全部博文(254)

文章存档

2016年(6)

2015年(2)

2014年(74)

2013年(93)

2012年(12)

2011年(2)

2010年(51)

2009年(14)

分类: LINUX

2013-11-15 11:17:19

作者:good bai   

后来一段时间,对linux下的程序调试有了一些新的认识,所以补充出了这一篇,前一篇文章可以查看这里 Linux下程序的调式(gdb) 。

一 调式器介绍 

1 gdb,快速高效,功能强大,相对操作复杂。 
2 DDD,gdb图形前端,提供了比gdb更好的界面操作,直观的界面,更友好的鼠标操作之类。同时保留了gdb的命令行终端。 
3 eclipse,界面更加完善,对用户友好的功能丰富,够多的傻瓜式操作。操作简单,但一些功能可能没有提供操作接口。(据说可以直接启用gdb线程在终端下操作)。 

二 gdb的几则使用 

1 watchpointer [(条件)]/变量名,观察点,在设置的变量(或者是条件)发生时,中断执行(据说在大型循环内部,基于条件的观察点可能导致调试器很慢)。使用如: 
gdb>watch (num >30) #当num的值大于30时中断 

2 frame,切换当前执行栈(即函数栈),一般编号0为当前执行栈,它的父调用函数栈依次为1,2...,使用下面的命令,可以切换想要查看的栈空间,但该操作不会改变进程的执行序列。 
gdb>frame 栈编号 

3 continue,继续执行到下一个断点(或者到程序结束)。 

三 信号与段错误 

1 segment fault(段错误),一般是因为进程访问了非法内存地址,操作系统为了保护系统会中断该进程的执行,但不是所有的非法内存访问会导致段错误 
1)内存管理的基本单元是页,所以访问权限也是以页为单位来标识的,那么有些情况,一些操作虽然已经访问了允许之外的内存空间,但因为该页对它具有访问权限,所以不会发生错误。 
2)非法访问内存应该是说进程访问了超出它访问权限之外的内存空间,比如访问了内核保护空间等其他,但还有一种情况(我个人以为):就是进程对自身内存空间管理不善,导致一些内存区域被不正常的操作改写,丢失数据(此情况也可能是一些恶意的人为因素)。那么这种情况,内存管理系统是不可能探知到的,也更不会出现什么段错误之类,这个可能只能由用户自己小心严谨编程来保证可靠性。 
所以没有发生段错误,不表示内存操作没有错误。断错误实质是默认的信号处理操作对SIGSEGV信号响应的结果。 

2 signal(信号),一般系统会给我们的程序实现好了一套默认的信号处理函数,如段错误信号(SIGSEGV)发生时直接报错退出,中断信号(SIGINT,Ctrl+c操作对应)发生时中断运行,一些特殊情况下当需要特殊的信号处理操作时,可以使用signal函数搞定,signal函数符合POSIX规范,具体使用可以参考man手册。有一个特殊的现象:我试着使用下面的代码把段错误的处理函数定义为空: 
signal(SIGSEGV, NULL); 
执行程序后段错误发生时,程序报错”segment fault“并退出。 
当修改SIGSEGV信号响应处理函数为自定义的非空函数时,该函数被反复调用执行执行,即程序不再继续执行。貌似这是系统为保证程序的可靠性和安全性而作了强制限制。 

四 一些其他调试思路 

功能调用跟踪调试,对于一些无法依附源码调试的软件,可以借助strace和ltrace工具来跟踪程序执行时的大概行为,strace可以跟踪每一个系统调用的详细情况,包括调用名,传递的参数和返回值。ltrace与strace类似,不同的是它用来跟踪库的调用情况。 

其他内容: 

1) 实际测试发现在不同的linux版本下(gcc版本不同),未赋值的指针值不确定,有些为NULL,而有些则为随机值。 

五 数据内存存储 

1 经测试intel e8400 cpu平台,linux 2.18 x86_64系统下,存储类型为小端存储,即数值位的低位存在内存较低的位置,高位存储在高位。 
如:int num=0x1122; 
实际内存情况是 
0x***001 -- 0x22 
0x***002 -- 0x11 
2 数值存储形式 
数值以补码形式存储,32位机上,数值与内存形式对应表如下: 
int 1 0x00000001 
int 0 0x00000000 
int -1 0x11111111 
int 100 0x00000064 
3 非零值在c中表示真值。 
TRUE,FALSE本质上是一个预处理宏,使用时需要小心。 

六 gdb多进程调试方法 

1 使用attach命令把gdb附加的目标进程,无参数启动gdb,使用attach命令后加pid的方式完成附加,如果你有该程序调试符号表文件,也可以使用file命令附加,这样就可以像正常调试一样操作了。调试完成后使用detach命令解除附加,使目标进程恢复正常允许。 

2 较新版的gdb已经开始简单支持多进程调试了(貌似依赖于内核版本),通常在fork一个新进程后,gdb默认跟踪父进程往下执行,不会管子进程的存在。新的支持多进程的gdb可以使用set follow_fork_mode parent/child命令指定gdb在fork执行之后follow那个进程。 

3 gdb warpper,没有试过,不了解。 


参考: 
使用 GDB 调试多进程程序 田 强 (
), IBM中国软件开发中心 
http://www.ibm.com/developerworks/cn/linux/l-cn-gdbmp/index.html
阅读(1075) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~