Saturday, February 17, 2007

C\C++ Boundary and Error Check (2)

Sample:
//ilist 中普通版本的insert()操作
//以一个待插入的值以及一个ilist_item 指针作为参数,新的项被插
//在这个指针所指的项的后边
inline void
ilist::
insert( ilist_item *ptr, int value )
{
new ilist_item( value, ptr );
++_size;
}

  • 一种方案是通过调用C标准库abort()函数来终止程序该函数在C头文件cstdlib 中.
#include<cstdlib>
// ...
if ( ! ptr )
abort();

  • 另一种方案是使用assert()宏来终止程序,但首先要声明引起断言的条件.
#include<cassert>
// ...
assert( ptr != 0 );

  • 第三种方案是抛出一个异常例如
if ( ! ptr )
throw "Panic: ilist::insert(): ptr == 0";

一般地我们应该尽可能地避免终止程序.终止程序实际上是对用户落井下石,而我们或者支持部门可以分离并解决这些问题.

如果我们在错误点上不能继续处理,那么一般来说抛出异常比终止程序更好一些.异常会把控制权传送到程序先前被执行的部分,而它们有可能能够解决这个问题.

assert()是C语台标准库中提供的一个通用预处理器宏.在代码中常利用assert()来判断一个必需的前提条件,以便程序能够正确执行.

为了使用assert() 必须包含与之相关联的头文件
#include <assert.h>
assert.h 是C 库头文件的C 名字,C++程序可以通过C库的C名字或C++名字来使用它,这个头文件的C++名字是cassert
#include <cassert>
using namespace std;
assert宏将会判断表达式,如果一个表达式为真,执行将继续,否则,程序将显示一条消息并且暂停,你可以选择忽视这条错误并继续、终止这个程序或者是跳到Debug器中。

  • 如何使用一个ASSERT宏去验证一个语句。
void foo(char *p, int size)
{
ASSERT(p != 0); //确认缓冲区的指针是有效的
ASSERT((size 〉= 100); //确认缓冲区至少有100个字节
// Do the foo calculation
}
这些语句不产生任何代码,除非—DEBUG处理器标志被设置。Visual C++只在Debug版本设置这些标志,而在Release版本不定义这些标志。

两个assertions将产生如下代码:
//ASSERT(p != 0);
do{if(!(p != 0) && AfxAssertFailedLine(—FILE—,—LINE—))AfxDebugBreak();
} while(0);
//ASSERT((size 〉= 100);
do{if(!(size 〉= 100) && AfxAssertFailedLine(—FILE—,—LINE—))AfxDebugBreak();
} while(0);
If语句将求取表达式的值并且当结果为零时调用AfxAssertFailedLine()函数。这个函数将弹出一个对话框,其中提供三个选项“取消、重试或忽略”,当你选取“重试”时,它将返回TRUE。重试将导致对AfxDebugBreak()函数的调用,从而激活调试器。

我们的实现能够识别空指针,并将其视为把value 插入链表头的请求

inline void
ilist::
insert( ilist_item *ptr, int value )
{
if ( !ptr )
insert_front( value ); //将value插入链表头
else {
bump_up_size(); //++_size;
new ilist_item( value, ptr );
}
}

直接返回给掉用者处理

inline bool
ilist::
insert( ilist_item *ptr, int value )
{
if ( !ptr )
return false;
else {
bump_up_size(); //++_size;
new ilist_item( value, ptr );
}
return true;
}

//声明一个ErrorCode的枚举
enum e_Error{
e_ErrorOK,
e_ErrorNullPointer,
……
}

inline e_Error
ilist::
insert( ilist_item *ptr, int value )
{
if ( !ptr )
return e_ErrorNullPointer;
else {
bump_up_size(); //++_size;
new ilist_item( value, ptr );
}
return e_ErrorOK;
}



Digg!

No comments: