用于改进代码可调试性的输入,除了日志和错误代码
除了错误代码,错误字符串和日志之外,是否还有其他function可以合并到代码中以增加在代码运行期间获取调试/跟踪信息,这有助于在运行时调试问题(或让我们知道发生了什么)?
以下是在分段错误时将堆栈跟踪发送到文件的代码示例
#include#include #include #include static void signal_handler(int); static void dumpstack(void); static void cleanup(void); void init_signals(void); void panic(const char *,...); struct sigaction sigact; char * progname; int main(int argc,char ** argv){ char * s; progname = *(argv); 的atexit(清理); init_signals(); printf(“关于通过将零分配给* s \ n来判断故障”); * s = 0; sigemptyset(&sigact.sa_mask); 返回0; } void init_signals(void){ sigact.sa_handler = signal_handler; sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; sigaction(SIGINT,&sigact,(struct sigaction *)NULL); sigaddset(&sigact.sa_mask,SIGSEGV); sigaction(SIGSEGV,&sigact,(struct sigaction *)NULL); sigaddset(&sigact.sa_mask,SIGBUS); sigaction(SIGBUS,&sigact,(struct sigaction *)NULL); sigaddset(&sigact.sa_mask,SIGQUIT); sigaction(SIGQUIT,&sigact,(struct sigaction *)NULL); sigaddset(&sigact.sa_mask,SIGHUP); sigaction(SIGHUP,&sigact,(struct sigaction *)NULL); sigaddset(&sigact.sa_mask,SIGKILL); sigaction(SIGKILL,&sigact,(struct sigaction *)NULL); } static void signal_handler(int sig){ if(sig == SIGHUP)恐慌(“致命:程序被绞死\ n”); if(sig == SIGSEGV || sig == SIGBUS){ dumpstack(); 恐慌(“致命:%s故障。记录StackTrace \ n”,(sig == SIGSEGV)?“分段”:((sig == SIGBUS)?“总线”:“未知”)); } if(sig == SIGQUIT)恐慌(“QUIT信号结束程序\ n”); if(sig == SIGKILL)恐慌(“KILL信号结束程序\ n”); if(sig == SIGINT); } void panic(const char * fmt,...){ char buf [50]; va_list argptr; va_start(argptr,fmt); vsprintf(buf,fmt,argptr); va_end用来(argptr); fprintf(stderr,buf); 出口(-1); } static void dumpstack(void){ / *从http://www.whitefang.com/unix/faq_toc.html获得此例程 **第6.5节。 修改为重定向到文件以防止混乱 * / char dbx [160]; sprintf(dbx,“echo'where \ ndetach'| dbx -a%d>%s.dump”,getpid(),progname); 系统(DBX); 返回; } void cleanup(void){ sigemptyset(&sigact.sa_mask); / *在这里做任何清理工作* / }
在函数dumpstack
,需要更改dbx
以适应您的调试器,例如GNU调试器的gdb
,几年前我在AIX机器上编程时使用了此代码。 注意如何设置信号,如果发生SIGSEGV故障,处理程序会将堆栈转储到扩展名为.dump
的文件。 该代码演示了分段错误并转储堆栈跟踪。
这是我最喜欢的代码。
希望这会有所帮助,最好的问候,汤姆。
- 在没有优化的情况下构建,以尽可能多地保留代码的“意图”
- 在调试模式下构建,以添加符号信息
- 不要剥离可执行文件(在Linux / Unix系统上),以保留尽可能多的符号信息供调试器使用
在为Linux构建时,我希望能够从信号处理程序中打印堆栈回溯 。 这有助于调试崩溃( SIGSEGV
)或允许我向程序发送信号以在运行时启动堆栈回溯。 核心转储在调试崩溃时也很有用(同样在Linux中)。