捕获和记录异常






4.50/5 (3投票s)
一种在 C++ 中捕获异常并记录它们的简单方法。
引言
C++ 开发人员通常试图通过在他们的代码中放置日志语句(cout
等)来查找错误/异常,以查找发生了什么。 有些人选择使用 Dr.Watson 等软件来获取调用堆栈并费力找到异常位置。 众所周知,捕获异常的唯一方法是使用 try
/catch
块。 但放置这些块会降低代码的可读性,并且可能更容易出错,因为 catch
块中的语句。
我在这里介绍一些易于使用的宏,它们将这些 try
/catch
块放入代码中。 这些宏将允许您捕获异常并将异常位置记录到文件中。 如果您在代码中使用这些宏,则每当发生异常时,您都将能够看到调用堆栈。
也可以禁用异常抛出,以便您的程序可以无需异常而运行。
Using the Code
使用宏非常简单。 假设您有一个名为 myMethod
的函数
void myMethod()
{
EXLOG_START
...
...
EXLOG_END
}
EXLOG_START
是一个简单的 try
表达式。 另一方面,EXLOG_END
是带有错误日志记录机制的 catch
块。
当 myMethod
函数中发生异常时,它将被捕获并记录在一个文件中。 之后,如果没有禁用异常抛出(将被告知),则异常将被抛给 myMethod
的调用者函数。 如果您在函数中放置了 EXLOG
语句,则异常将被记录到 main
函数。
您可以禁用 EXLOG 的异常抛出,以便捕获异常、记录异常,并且程序将尝试继续运行。 您可以在代码的任何部分使用以下方法设置它
EXLOG::setIsThrowExceptions(false); //default: true
一些函数可能会返回值而不是 void
。 对于这些函数,您应该使用另一个宏 EXLOG_END_WITH_RETURN
,以允许这些函数在发生异常时返回值
int myMethodWithReturn()
{
EXLOG_START
...
...
EXLOG_END_WITH_RETURN(-1)
}
因此,如果存在异常,myMethodWithReturn
将返回 -1(假设这是此函数的默认值),并且调用者将获得 -1,并且程序将继续运行。
除了这些宏之外,ExLogger
类也很重要。 它是将信息记录到文件的类。 它使用 boost 的日期时间类为文件/日志获取唯一名称。 因此,您应该将 boost 的库添加到您的项目中。
您还可以使用 ExLogger
将任何内容记录到文件中。 它是一个单例类,它重载了 <<
运算符,这使您可以像写入 cout
一样编写简单易读的代码。 您可以使用宏 EXLOG
获取一个实例
EXLOG << myInt << "sth" << myValue << EXLOG_ENDL("");
EXLOG_ENDL
类似于 std::endl
,它会导致日志流被刷新到文件中。
关注点
在代码中,EXLOG
宏可以用定义更改:EXLOG_ENABLED
。 我已将此定义放入标头中,但您可以将其放入您的预处理器部分,以便您可以使用一个定义启用/禁用 EXLOG
相关代码。
如果未启用 EXLOG_ENABLED
,则宏将被替换为 //
注释表达式。 因此,表达式将被注释掉。 这种用法只有一个小问题:如果想用这个定义禁用 EXLOG
语句,应该把 EXLOG
语句放在一行。
所以,例如
EXLOG << myInt << "sth" << myValue << EXLOG_ENDL("");
是安全的。 但
EXLOG << myInt <<
"sth" << myValue
<< EXLOG_ENDL("");
如果您未定义 EXLOG_ENABLED
,将导致编译错误。
但我认为这种方法比使用
#ifdef _DEBUG
Exlogger::instance() << myInt << "sth" << myValue << EXLOG_ENDL("");
#endif
注释
- 使用默认的项目设置,硬件相关的异常,例如除以零、悬空指针使用等,无法使用标准的
try
/catch
块捕获。 您应该通过以下路径更改您的项目设置以启用此功能
Project Properties >> C/C++ >> Code Generation >> Enable C++ Exceptions
并将该值设置为“是,带 SEH 异常(/EHa)”。
_SECURE_SCL=0 ve _HAS_ITERATOR_DEBUGGING=0
但请记住在所有导入的项目中设置这些预处理器设置! 因此,最后一个设置是可选的。 如果您没有定义这些预处理器值,则 STL 异常可能不会被捕获/记录,但会通过断言通知您。
讨论
您可能认为放置 try
/catch
可能会影响性能。 但是在使用 try
/catch
块时,您可以放心。 我搜索了很多论坛,也进行了性能测试。 使用 try
/catch
块和不使用它们之间只有微不足道的差异。
进行安全开发。 :)