我使用GCC编译器在Linux上工作。当我的c++程序崩溃时,我希望它自动生成一个堆栈跟踪。
我的程序由许多不同的用户运行,它也可以在Linux、Windows和Macintosh上运行(所有版本都使用gcc编译)。
我希望我的程序能够在崩溃时生成堆栈跟踪,下次用户运行它时,它会问他们是否可以将堆栈跟踪发送给我,这样我就可以跟踪到问题。我可以处理发送信息给我,但我不知道如何生成跟踪字符串。什么好主意吗?
我使用GCC编译器在Linux上工作。当我的c++程序崩溃时,我希望它自动生成一个堆栈跟踪。
我的程序由许多不同的用户运行,它也可以在Linux、Windows和Macintosh上运行(所有版本都使用gcc编译)。
我希望我的程序能够在崩溃时生成堆栈跟踪,下次用户运行它时,它会问他们是否可以将堆栈跟踪发送给我,这样我就可以跟踪到问题。我可以处理发送信息给我,但我不知道如何生成跟踪字符串。什么好主意吗?
当前回答
Ulimit -c <value>设置unix上的核心文件大小限制。缺省情况下,内核文件大小限制为0。可以使用ulimit -a查看ulimit值。
此外,如果您从gdb内部运行程序,它将在“分段违规”(SIGSEGV,通常当您访问未分配的内存块时)时停止程序,或者您可以设置断点。
DDD和nemiver是GDB的前端,这使得新手更容易使用GDB。
其他回答
Ulimit -c <value>设置unix上的核心文件大小限制。缺省情况下,内核文件大小限制为0。可以使用ulimit -a查看ulimit值。
此外,如果您从gdb内部运行程序,它将在“分段违规”(SIGSEGV,通常当您访问未分配的内存块时)时停止程序,或者您可以设置断点。
DDD和nemiver是GDB的前端,这使得新手更容易使用GDB。
* nix: 你可以拦截SIGSEGV(通常这个信号是在崩溃之前发出的),并将信息保存到一个文件中。(除了可以使用GDB进行调试的核心文件之外)。
赢得: 从msdn检查这个。
你也可以看看谷歌的chrome代码,看看它是如何处理崩溃的。它有一个很好的异常处理机制。
我研究这个问题有一段时间了。
深埋在谷歌性能工具README
http://code.google.com/p/google-perftools/source/browse/trunk/README
谈到libunwind
http://www.nongnu.org/libunwind/
很乐意听听对这个图书馆的意见。
使用-rdynamic的问题是,在某些情况下,它会相对显著地增加二进制文件的大小
感谢calorticgeek让我注意到addr2line实用程序。
我写了一个快速和肮脏的脚本来处理这里提供的答案的输出: (非常感谢jschmier!)使用addr2line实用程序。
脚本只接受一个参数:包含jschmier实用程序输出的文件名。
对于跟踪的每一层,输出应该打印如下内容:
BACKTRACE: testExe 0x8A5db6b
FILE: pathToFile/testExe.C:110
FUNCTION: testFunction(int)
107
108
109 int* i = 0x0;
*110 *i = 5;
111
112 }
113 return i;
代码:
#!/bin/bash
LOGFILE=$1
NUM_SRC_CONTEXT_LINES=3
old_IFS=$IFS # save the field separator
IFS=$'\n' # new field separator, the end of line
for bt in `cat $LOGFILE | grep '\[bt\]'`; do
IFS=$old_IFS # restore default field separator
printf '\n'
EXEC=`echo $bt | cut -d' ' -f3 | cut -d'(' -f1`
ADDR=`echo $bt | cut -d'[' -f3 | cut -d']' -f1`
echo "BACKTRACE: $EXEC $ADDR"
A2L=`addr2line -a $ADDR -e $EXEC -pfC`
#echo "A2L: $A2L"
FUNCTION=`echo $A2L | sed 's/\<at\>.*//' | cut -d' ' -f2-99`
FILE_AND_LINE=`echo $A2L | sed 's/.* at //'`
echo "FILE: $FILE_AND_LINE"
echo "FUNCTION: $FUNCTION"
# print offending source code
SRCFILE=`echo $FILE_AND_LINE | cut -d':' -f1`
LINENUM=`echo $FILE_AND_LINE | cut -d':' -f2`
if ([ -f $SRCFILE ]); then
cat -n $SRCFILE | grep -C $NUM_SRC_CONTEXT_LINES "^ *$LINENUM\>" | sed "s/ $LINENUM/*$LINENUM/"
else
echo "File not found: $SRCFILE"
fi
IFS=$'\n' # new field separator, the end of line
done
IFS=$old_IFS # restore default field separator
你可以使用DeathHandler -一个小的c++类,它为你做所有的事情,可靠。