qmake生成makefile,生成core dump文件
新建build文件夹
mkdir build
把Makefile文件生成到build目录下
qt creator 生成.pro文件,qmake生成makefile文件,需要运行
qmake -o Makefile ../*.pro
编译生成可执行文件
make
1 、当程序出现异常时通常伴随着会收到一个由内核发过来的异常信号 (查看 kill -l),
如当对内存出现非法访问时将收到段错误信号SIGSEGV,然后才退出。
利用这一点,当我们在收到异常信号后将程序的调用栈进行输出
2、捕获系统异常信号输出程序的调用栈: 头文件<execinfo.h>提供了三个相关的函数
int backtrace(void **buffer, int size); // 用于获取堆栈的地址信息
char **backtrace_symbols(void *const *buffer, int size); //把堆栈地址翻译成我们易识别的字符串,其被存放在buffer中
void backtrace_symbols_fd(void *const *buffer, int size, int fd); //把字符串堆栈信息输出到文件中
注意: GCC编译链接的话,加上“-rdynamic”参数,这个参数的意思是告诉ELF连接器添加“-export-dynamic”标记,这样所有的符号信息symbols就会添加到动态符号表中,以便查看完整的堆栈信息。
static函数不会导出符号信息symbols,在backtrace中无效。
某些编译器的优化选项对获取正确的函数调用堆栈有干扰,内联函数没有堆栈框架,删除框架指针也会导致无法正确解析堆栈内容。
设置core文件生成
1)使用命令ulimit -c filesize命令
若ulimit -c unlimited 则标识此core文件的大小不受限制
若指定filesize,如果生成的信息超过此大小,将会被裁剪,最终生成一个不完整的core文件,在调
试此core文件时,gdb会提示错误。
2)但是若想整个系统中生效则在shell里面设置是不行的,方法如下:
(1)编辑/root/.bash_profile文件,在其中加入ulitmit -S -c unlimited
(2)source /root/.bash_profile
core文件的保存位置和文件名格式
echo “/corefile/core-%e-%p-%t” > core_pattern,可以将core文件统一生成到/corefile目录
gdb调试命令:
1、gdb 程序名 或者gdb 程序名 core文件
l :列出代码
break n :第n行加断点
n :next 单步执行
s :step 进入函数内部
until n :运行直到第n行
run :运行
print 变量 :打印值
where :查看程序执行位置
bt :函数调用堆栈
定位到出错代码:where或backtrace,将显示#x这样的堆栈信息
程序异常时主动打印堆栈信息,函数调用堆栈信息
在Linux上的C/C++编程环境下,我们可以通过如下三个函数来获取程序的调用栈信息。
#include <execinfo.h>
/* Store up to SIZE return address of the current program state in
ARRAY and return the exact number of values stored. */
int backtrace(void **array, int size);
/* Return names of functions from the backtrace list in ARRAY in a newly
malloc()ed memory block. */
char **backtrace_symbols(void *const *array, int size);
/* This function is similar to backtrace_symbols() but it writes the result
immediately to a file. */
使用它们的时候有一下几点需要我们注意的地方:
backtrace的实现依赖于栈指针(fp寄存器),在gcc编译过程中任何非零的优化等级(-On参数)或加入了栈指针优化参数-fomit-frame-pointer后多将不能正确得到程序栈信息;
backtrace_symbols的实现需要符号名称的支持,在gcc编译过程中需要加入-rdynamic参数;
内联函数没有栈帧,它在编译过程中被展开在调用的位置;
尾调用优化(Tail-call Optimization)将复用当前函数栈,而不再生成新的函数栈,这将导致栈信息不能正确被获取。