设为首页 加入收藏

TOP

POCO C++库学习和分析 -- 异常、错误处理、调试 (四)
2014-11-24 03:15:31 】 浏览:9118
Tags:POCO 学习 分析 异常 错误 处理 调试

try
{
pExc->rethrow();
}
catch (Poco::Exception& exc)
{
std::cerr << exc.displayText() << std::endl;
}
delete pExc;
return 0;
}

2. 断言
POCO库中提供了一些断言的宏来进行运行时检查,这些断言能够提供出错代码的行号和文件信息。
1. Debugger::_assert(cond)
如果cond ≠ true时,抛出一个AssertionViolationException异常。
2. poco_assert_dbg(cond)
同poco_assert类似,但是只在debug模式下起作用
3. poco_check_ptr(ptr)
如果ptr为空,则抛出NullPointerException异常
4. poco_bugcheck(), poco_bugcheck_msg(string)
抛出BugcheckException异常

POCO的断言类在debug调试模式下(比如在Visual C++)中时,会触发一个breakpoint。比如:
[cpp]
void foo(Bar* pBar)
{
poco_check_ptr (pBar);
...
}
void baz(int i)
{
poco_assert (i >= 1 && i < 3);
switch (i)
{
case 1:
...
break;
case 2:
...
break;
default:
poco_bugcheck_msg("i has invalid value");
}
}

void foo(Bar* pBar)
{
poco_check_ptr (pBar);
...
}
void baz(int i)
{
poco_assert (i >= 1 && i < 3);
switch (i)
{
case 1:
...
break;
case 2:
...
break;
default:
poco_bugcheck_msg("i has invalid value");
}
}
这主要是因为Poco中的断言类是通过Poco::Debugger去实现的,在Poco::Debugger底层调用了不同操作系统的API,去判断程序是否处于调试状态。如VC下,调用了
[cpp]
BOOL WINAPI IsDebuggerPresent(VOID);
VOID WINAPI DebugBreak(VOID);

BOOL WINAPI IsDebuggerPresent(VOID);
VOID WINAPI DebugBreak(VOID);

3. NDC(Nested Diagnostic Context)
3.1 概述
NestedDiagnosticContext是为了多线程诊断而设计的。我们在写程序时,一般都需要同时处理多个线程。为了更加便捷的处理多线程情况,为每个线程产生各自的日志。Neil Harrison 在他的书中"Patterns for Logging Diagnostic Messages," in Pattern Languages of Program Design 3, edited by R. Martin, D. Riehle, and F. Buschmann (Addison-Wesley, 1997) 中提出了一个方法。独特地标记每个日志请求,用户把上下文信息送入NDC,NDC是 Nested Diagnostic Context的缩写。在这本书里提到了3种日志方法,分别是:
1. DiagnosticLogger
分离日志和程序其他模块
2. TransactionalBuckets
事务桶,为事务单独建立日志
3. TypedDiagnostics
类型化诊断,为所有的诊断信息提供统一的展现


我们还是回到Poco中的NDC上。在Poco中和NDC相关的内容包括了,NestedDiagnosticContext类,NDCScope类,宏poco_ndc和poco_ndc_dbg。其中NestedDiagnosticContext类维护一个NDC对象,其中包括了上下文的栈信息,有函数方法名,源文件代码文件名,行号。宏poco_ndc(func) or poco_ndc_dbg(func)申明了一个NDCScope对象。而NDCScope对象则完成了上下文的入栈工作。下面是一个例子:

[cpp]
#include "Poco/NestedDiagnosticContext.h"
#include
void f1()
{
poco_ndc(f1);
Poco::NDC::current().dump(std::cout);
}
void f2()
{
poco_ndc(f2);
f1();
}
int main(int argc, char** argv)
{
f2();
return 0;
}

#include "Poco/NestedDiagnosticContext.h"
#include
void f1()
{
poco_ndc(f1);
Poco::NDC::current().dump(std::cout);
}
void f2()
{
poco_ndc(f2);
f1();
}
int main(int argc, char** argv)
{
f2();
return 0;
}


3.2 实现
3.2.1 线程本地存储
在Poco中实现时,用了一些小技巧,即线程本地存储。我们来看Poco中TLS的类图:

\

CurrentThreadHolder类是TLS实现的具体类,在每个Thread对象中包含了一个CurrentThreadHolder对象。Thread创建的时候,CurrentThreadHolder会调用不同操作系统的API函数,获取并保存一个固定槽位,用于保存Thread对象的指针。
每个Thread对象中还包含了一个ThreadLocalStorage对象。ThreadLocalStorage类用于保存具体的线程信息数据,它是一个TLSSlot对象的集合。通过泛型实现TLSSlot后,ThreadLocalStorage可用于保存任何数据的。

使用了TLS技术后,调用Thread的静态函数current可以获取到每个线程对象Thread的指针,然后再通过这个Thread对象的指针,可以获取到ThreadLocalStorage对象,并最终获取或保存数据于TLSSlot中。

通过类的静态函数获取类实例的指针,在C++中是不存在的,这需要操作系统支持,只有Thread对象才能做到这一点。


3.2.2 NDC
在来看一张Poco中NDC类的类图:

\

使用者通过调用宏poco_ndc和poco_ndc_dbg,来构建一个NDCScope对象

首页 上一页 1 2 3 4 5 下一页 尾页 4/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇HDU1556 color the ball][树状数.. 下一篇poj3006 Dirichlet's Theorem..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目