core dump, 通常译作内存转储,core之所以译作内存,而不是核心,纯属“著名”的历史原因,因为早期的内存有一个叫磁芯(magnectic core)的东西。内存转储会在磁盘中产生一个文件,是某个进程在转储时刻的内存映像及寄存器等信息。内存转储通常发生在进程执行了有致命错误的指令时,常见的就是著了名的Segmentation fault,即段错误,而导致段错误的就是C/C++编程中经常发生的内存非法访问。内存转储操作由操作系统内核进行。当然,内存转储还可以是用户主动发起请求,内核执行转储。
内存转储对于程序调试是至关重要的。利用内存转储文件(core files)对程序进行调试是一种异步的静态调试,所谓异步是指异常发生与调试不是在同一时刻,所谓静态指的是core files保存的只是转储时刻进程的内存状态。比如,一个长期运行的服务程序,我们不知道哪里有bug,该bug何时被触发,这种情况下,利用异常发生时的转储文件就可以在一定程度上定位出异常发生的原因。另外,对于非致命性错误,比如死锁或者死循环,进程不会自动结束,通常内核也不会主动杀掉这种进程,这时用户就可以请求内核将该进程进行内存转储,以此来查看进程的运行状态(比如各进程的堆栈)。
Posts Tagged ‘GDB’
调试内存转储文件。内存转储文件(core dump)是程序发生严重错误时操作系统产生的文件,它包含了程序崩溃时占用的内存页面的拷贝,因此使用core文件在一定程度上可以再现崩溃前夕程序的状态。
多种原因下程序会崩溃,从而被系统终止,生成core文件,经常见到的是访存错误(段错误,Segment fault)。另外,系统是否生成core文件以及core文件的最大尺寸还受系统参数的控制。例如ubuntu下面普通用户程序是不允许生成core文件的,这可以使用ulimit命令来修改。不带参数的ulimit -c输出当前core文件的最大允许值,为了能够生成core文件,使用ulimit -c size设置大小,简单地,ulimit -c unlimited将其设为没有限制。
1 2 3 4 5 6 7 8 9 10 | void foo(const char* s) { char c = *s; } int main() { foo(0); return 0; } |
列位安好。简单总结下GDB调试器的使用。
准备
默认情况下,gcc/g++编译的可执行文件是不包含调试信息的,GDB是一个源代码级的调试器,使用GDB调试程序需要程序的源代码、符号及其对应的行号等,其中符号和行号可以是单独的文件,亦可以在编译时嵌入到可执行文件中。使用gcc/g++时使用-g选项即可将必要的调试信息包含到可执行文件中,使用-g3选项还可以将源代码中的宏信息也包含进去。
另外,调试过程中需要随时查看源代码,但源代码并没有包含到可执行文件中。通常GDB在当前目录查找源文件,但某些情况下(比如调试系统命令)需要手动指明源代码的查找目录,directory ~向GDB指明到$HOME下查找源文件。
启动
GDB的启动很灵活,它的各种特性,你可以在Shell下通过选项和参数指定,也可以在GDB启动之后在GDB自己的命令行下使用GDB内置的命令来指定。最常用的是直接使用命令gdb PROGRAM启动,这样gdb自动加载符号表等调试信息。若要向被调试程序传递参数,可以采用gdb –args program ARG1 ARG2的形式,其中–args(或者-args)是必须的,它告诉GDB该选项之后已经没有GDB需要的选项了。另外,还可以直接使用gdb启动,然后使用file program加载调试信息。此时若要设置被调试程序的参数,可以使用set命令的args子命令,如set args ARG1 ARG2. 还有一种传递参数的方法,在下面介绍。
| 命令 | 描述 |
|---|---|
| backtrace(或bt) | 查看各级函数调用及参数 |
| finish | 连续运行到当前函数返回为止,然后停下来等待命令 |
| frame(或f) 帧编号 | 选择栈帧 |
| info(或i) locals | 查看当前栈帧局部变量的值 |
| list(或l) | 列出源代码,接着上次的位置往下列,每次列10行 |
| list 行号 | 列出从第几行开始的10行源代码 |
| list 函数名 | 列出某个函数的源代码 |
| next(或n) | 执行下一行语句 |
| print(或p) | 打印表达式的值,通过表达式可以修改变量的值或者调用函数 |
| quit(或q) | 退出gdb调试环境 |
| set var | 修改变量的值 |
| start | 开始执行程序,停在main函数第一行语句前面等待命令 |
| step(或s) | 执行下一行语句,如果有函数调用则进入到函数中 |
| break(或b) 行号 | 在某一行设置断点 |