可以捕捉所有未知异常和生成包含程序名的Core dump 文件。
/*
* DebugUtility.h
*
* Created on: Jun 4, 2014
* Author: root
*
* Use following two ways to help debugging application when application is crashed:
*
* 1 Turn on core dump and generate core dump file by forking child process and rename the child process dump
* file to new name. Including application name in core dump file is more easy to identify then default
* file name.
* 2 Overwrite terminate() to handle un-handled exception and print backtrace before abort.
* Use gdb to get backtrace and save into log file /tmp/[app_name]_backtrace
*
* Requriement:
* Linux, gcc, gdb
*
* How to use it:
*
* Add following lines at the beginning of main function to initialize:
* Be attention: app_name can't include path.
*
* char * app_name;
* if ( (app_name = strrchr(argv[0], '/')) == NULL )
* {
* DebugUtility::GetInstance().Setup(argv[0], true);
* }
* else
* {
* DebugUtility::GetInstance().Setup(app_name + 1, true);
* }
*
* To generate core dump file, you need to call DebugUtility::GetInstance().GenerateCoreDump() in signal
* handler code.
*
* For example:
*
* void signal_handler(int signal, siginfo_t * p_signinfo, void * p_context)
* {
* DebugUtility::GetInstance().GenerateCoreDump();
* exit(0);
* }
*
* In main function:
*
* struct sigaction sa;
* sa.sa_sigaction = signal_handler;
* sigemptyset(&sa.sa_mask);
* sa.sa_flags = SA_RESTART | SA_SIGINFO;
* sigaction(SIGTERM, &sa, (struct sigaction *) NULL);
*
* For application name test, if it crashed, you should be able to find core dump file core.test.[pid].
*
* For application name test, if it quit because of raised exception, you should be able to find backtrace
* log file /tmp/test_backtrace
*/
#ifndef DEBUGUTILITY_H_
#define DEBUGUTILITY_H_
#include <stdlib.h>
#include <string>
#include <sys/time.h>
#include <sys/resource.h>
#include <stdio.h>
#include <sys/wait.h>
#include <iostream>
#include <exception>
using namespace std;
class DebugUtility
{
public:
// Overwrite default global terminate handler to handle all un-handled exceptions
// Print backtrace before calling abort()
static void my_terminate()
{
DebugUtility::GetInstance().PrintBacktrace();
abort();
}
// Use singleton pattern to be sure only one DebugUtility object
static DebugUtility & GetInstance()
{
static DebugUtility instance;
return instance;
}
// Setup debug environment
// Parameters:
// app_name: application name which will be part of core dump and backtrace file.
// core_dump_enabled: whether enable core dump, by default true.
void Setup(string app_name, bool core_dump_enabled = true)
{
m_app_name = app_name;
m_core_dump_enabled = core_dump_enabled;
re_throw_flag = true;
if (m_core_dump_enabled)
EnableCoreDump();
std::set_terminate(DebugUtility::my_terminate);
}
// Generate core dump file based on application name
// For example application name test and pid is 12345, the core dump file is core.test.12345
void GenerateCoreDump()
{
try
{
if (m_core_dump_enabled)
{
// Fork child process to generate core dump file
// Then rename file name with application name
pid_t childpid = fork();
// child process generates core dump
if (childpid == 0)
{
// Send SIGABRT signal to terminate child process and generate core dump
abort();
}
if (childpid > 0)
{
waitpid(childpid, 0, 0);
}
char core_dump_file_name[1000];
char child_core_dump_file_name[1000];
// Rename the core dump name.
sprintf(core_dump_file_name, "core.%s.%d", m_app_name.c_str(), getpid());
sprintf(child_core_dump_file_name, "core.%d", childpid);
// try with core.pid
int rename_rval = rename(child_core_dump_file_name, core_dump_file_name);
if (rename_rval == -1)
{
// try with just core which may happen on HP server
rename_rval = rename("core", core_dump_file_name);
}
}
} catch (...)
{
// Catch all exceptions
}
}
// Try to re-throw exception again and print error message to std:cerr
// Generate back trace by using gdb and save under /tmp
// For example application name test, the backtrace file is /tmp/test_backtrace
void PrintBacktrace()
{
try
{
// try once to re-throw currently active exception
if (re_throw_flag)
{
re_throw_flag = false;
throw;
}
} catch (const std::exception &e)
{
std::cerr << __FUNCTION__ << " caught unhandled exception. what(): " << e.what() << std::endl;
} catch (...)
{
std::cerr << __FUNCTION__ << " caught unknown/unhandled exception." << std::endl;
}
try
{
char command_line[1000];
snprintf(command_line, sizeof(command_line), "gdb 2>/dev/null --batch -n -ex thread -ex bt full --exec=%s --pid=%d > /tmp/%s_backtrace",
m_app_name.c_str(), getpid(), m_app_name.c_str());
system(command_line);
} catch (...)
{
// Catch all exceptions
}
}
~DebugUtility()
{
}
private:
DebugUtility()
{
}
// Enable core dump
void EnableCoreDump()
{
m_core_dump_enabled = true;
// Set core dump limit to unlimited to enable core dump
rlimit core_limit =
{ RLIM_INFINITY, RLIM_INFINITY };
setrlimit(RLIMIT_CORE, &core_limit);
}
// Don't forget to declare these two. You want to make sure they
// are unaccessable otherwise you may accidently get copies of
// your singleton appearing.
DebugUtility(DebugUtility const&); // Don't Implement
void operator=(DebugUtility const&); // Don't implement
// Application name which will be used in backtrace file name and core dump file name
string m_app_name;
// Whether generate core dump file
bool m_core_dump_enabled;
// Re-throw flag
bool re_throw_flag;
};
#endif /* DEBUGUTILITY_H_ */
使用范例代码:
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "DebugUtility.h"
#include <exception>
#include <stdexcept>
#include <iostream>
using namespace std;
void signal_handler(int signal, siginfo_t * p_signinfo, void * p_context)
{
DebugUtility::GetInstance().GenerateCoreDump();
exit(0);
}
void func1()
{
throw std::runtime_error("test");
}
void func2()
{
func1();
}
int main(int argc, char* argv[])
{
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
char * app_name;
if ( (app_name = strrchr(argv[0], '/')) == NULL )
{
DebugUtility::GetInstance().Setup(argv[0], true);
}
else
{
DebugUtility::GetInstance().Setup(app_name + 1, true);
}
struct sigaction sa;
sa.sa_sigaction = signal_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART | SA_SIGINFO;
sigaction(SIGTERM, &sa, (struct sigaction *) NULL);
sigaction(SIGINT, &sa, (struct sigaction *) NULL);
func2();
return 0;
}
分享到:
相关推荐
Visual C++开发工具与调试技巧整理 1.如何在Release状态下进行调试2. Release和Debug有什么不同3....如何将一个通过ClassWizard生成的类彻底删除9. 如何将在workspace中消失的类找出来10. 如何清除所有的断点....
Dev-C++是一个Windows环境下的一个适合于初学者使用的轻量级 C/C++ 集成开发环境(IDE)。它是一款自由软件,遵守GPL许可协议分发源代码。它集合了MinGW中的GCC编译器、GDB调试器和 AStyle格式整理器等众多自由软件...
使用c++开发的简易串口调试工具,使用serial port类,可在vc6.0及以上调试
1.设计并定义一个交通工具类,并通过该类派生出新的类,编写程序定义这些类并测试它; 2.(选做)声明一个基类Shape,在此基础上派生Rectangle和Circle,二者都有GetArea()函数计算对象的面积,编写程序测试。 3...
9.l 高级调试工具 9.l.l 内存卸出 9.1.2 定位错误参数从何处传递而来 9.1.3 查找何处修改了指针 9.2 Class View窗口要素 9.2.1 ClassView窗口的 Grouped by Access功能 9.2.2 ClassView窗口的 Base ...
64位系统下可用Ollydbg调试工具不多啊,好不容易下了个,浪费的8分,为了方便大家。我传了一个。 可在最新的WIN7下使用哦。
Visual C++6.0是一个功能强大的可视化软件开发工具。自1993年Microsoft公司推出Visual C++1.0后,随着其新版本的不断问世,Visual C++已成为专业程序员进行软件开发的首选工具。 虽然微软公司推出了Visual C++.NET...
在Time类中增加拷贝构造函数的定义,主函数中调用该函数,运用调试工具跟踪,分析整个程序调用构造函数(包括拷贝构造函数)和析构函数的次数;再将f函数的形式参数分别修改为引用参数和指针参数(此时函数代码修改...
Visual C++ 6.0,简称VC或者VC6.0,是...Visual C++6.0由许多组件组成,包括编辑器、调试器以及程序向导AppWizard、类向导Class Wizard等开发工具。 这些组件通过一个名为Developer Studio的组件集成为和谐的开发环境。
这样的需求一般称作:插桩,也就是对于一个指定的目标函数,新建一个包装函数,来完成一些额外的功能,如动态调试等。 本文主要讲解什么是打桩,以及编译阶段打桩、链接阶段打桩、执行阶段打桩三种方式。
本书系编程语言先驱者Ivor Horton的经典之作,是C++编程方面最畅销的图书品种之一,不仅涵盖了Visual C++ 2008编程知识,还全面介绍了标准C++语言和C++/CLI。本书延续了Ivor Horton讲解编程语言的独特方法,从中读者...
C-Free是一款支持多种编译器的专业化C/C++集成开发环境(IDE)。利用本软件,使用者可以轻松地编辑、编译、连接、运行、调试C/C++程序。 1. 支持多编译器,可以配置添加其他编译器;(0) 目前支持的编译器类型: (1)...
第一篇 跟我练习 第1章 选择最方便的开发工具 1.1 可用的开发工具简介 1.1.1 Boland C++ 3.1/4.0/4.5 1.1.2 Boland C++ 5.0 1.1.3 Boland C++ Builder4.0/5.0/6.0 1.1.4 Visual C++ 6.0 1.2 Borland C++5.0...
《Visual C++范例大全》是孙皓创作的软硬件开发类书籍。 从工程应用出发,通过400余实例讲解VisualC++开发技术与要点涵盖VisualC++基本开发要素,也包含数据库,网络、多媒体等常用开发技术按照循序渐近、由浅入深...
全书共分成两大个部分:第一部分为iostream类参考,包括iostream编程和iostream类库按字母顺序参考两章;第二部分为运行库参考,包括运行库例程分类、全局变量和标准类型、全局常量、调试版C运行库和运行类库字母...
第一篇 跟我练习 第1章 选择最方便的开发工具 1.1 可用的开发工具简介 1.1.1 Boland C++ 3.1/4.0/4.5 1.1.2 Boland C++ 5.0 1.1.3 Boland C++ Builder4.0/5.0/6.0 1.1.4 Visual C++ 6.0 1.2 Borland C++5.0...
包括Visual C++ 6.0开发环境,程序设计基础,流程控制,函数,类和对象,对话框程序设计,MFC通用控件,MFC高级控件,菜单、工具栏和状态栏设计,文本、图形图像处理技术,程序调试,打印技术,文件操作,ADO数据库...
16.5 一个泛型句柄类 560 16.5.1 定义句柄类 561 16.5.2 使用句柄 562 16.6 模板特化 564 16.6.1 函数模板的特化 565 16.6.2 类模板的特化 567 16.6.3 特化成员而不特化类 569 16.6.4 类模板的部分特化 570 16.7 ...
第十章如何阅读程序代码……112 10.1整体把握法……112 10.2经验法……114 ...调试工具——Debug ……138 习题……141 第十二章如何编写程序代码……144 12.1程序设计的基本步骤……144 12.2三类问题……144 12.3函数的...
19.6 使用另一个记录集对象 19.6.1 添加记录集类 19.6.2 添加记录集的视图类 19.6.3 定制记录集 19.6.4 访问多个表视图 19.6.5 查看产品的订单 19.7 查看客户的详细情况 19.7.1 添加客户记录集 19.7.2 创建客户...