Friday, February 23, 2007
Saturday, February 17, 2007
C\C++ Boundary and Error Check (2)
Sample:
一般地我们应该尽可能地避免终止程序.终止程序实际上是对用户落井下石,而我们或者支持部门可以分离并解决这些问题.
如果我们在错误点上不能继续处理,那么一般来说抛出异常比终止程序更好一些.异常会把控制权传送到程序先前被执行的部分,而它们有可能能够解决这个问题.
assert()是C语台标准库中提供的一个通用预处理器宏.在代码中常利用assert()来判断一个必需的前提条件,以便程序能够正确执行.
为了使用assert() 必须包含与之相关联的头文件
do{if(!(size 〉= 100) && AfxAssertFailedLine(—FILE—,—LINE—))AfxDebugBreak();
//ilist 中普通版本的insert()操作
//以一个待插入的值以及一个ilist_item 指针作为参数,新的项被插
//在这个指针所指的项的后边
inline void
ilist::
insert( ilist_item *ptr, int value )
{
new ilist_item( value, ptr );
++_size;
}
//以一个待插入的值以及一个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();
// ...
if ( ! ptr )
abort();
- 另一种方案是使用assert()宏来终止程序,但首先要声明引起断言的条件.
#include<cassert>
// ...
assert( ptr != 0 );
// ...
assert( ptr != 0 );
- 第三种方案是抛出一个异常例如
if ( ! ptr )
throw "Panic: ilist::insert(): ptr == 0";
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器中。using namespace std;
- 如何使用一个ASSERT宏去验证一个语句。
void foo(char *p, int size)
{
ASSERT(p != 0); //确认缓冲区的指针是有效的
ASSERT((size 〉= 100); //确认缓冲区至少有100个字节
// Do the foo calculation
}
{
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);//ASSERT(p != 0);
do{if(!(p != 0) && AfxAssertFailedLine(—FILE—,—LINE—))AfxDebugBreak();
} while(0);
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 );
}
}
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,
……
}
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;
}
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;
}
Posted by
Jacob
at
9:03 AM
0
comments
Labels: IT, Programming DiggIt!
C\C++ Boundary and Error Check (1)
Sample:</br>
void CopyData(char *szData) {
char cDest[32];
strcpy(cDest,szData);
// 使用 cDest
...
}
char *szNames[] = {"Michael","Cheryl","Blake"};
CopyData(szName[1]);
void CopyData(char *szData) {
char cDest[32];
strcpy(cDest,szData);
// 使用 cDest
...
}
char *szNames[] = {"Michael","Cheryl","Blake"};
CopyData(szName[1]);
- 缓冲区溢出是指当计算机程序向缓冲区内填充的数据位数超过了缓冲区本身的容量,溢出的数据覆盖在合法数据上。
- 操作系统所使用的缓冲区又被称为堆栈,在各个操作进程之间,指令被临时存储在堆栈当中,堆栈也会出现缓冲区溢出。
- 缓冲区溢出是由编程错误引起的。如果缓冲区被写满,而程序没有去检查缓冲区边界,也没有停止接收数据,这时缓冲区溢出就会发生。
- 缓冲区溢出主要出现在 C 和 C++ 中,因为这些语言不执行数组边界检查和类型安全检查。
当编写 C 和 C++ 代码时,应注意如何管理来自用户的数据。如果某个函数具有来自不可靠源的缓冲区,请遵循以下规则:
- 要求代码传递缓冲区的长度并进行检查。
- 探测内存。
- 采取防范措施。
以下代码的问题在于函数不能判断 szName 的长度,这意味着将不能安全地复制数据。函数应知道 szName 的大小:
void Function(char *szName, DWORD cbName) { char szBuff[MAX_NAME];
// 复制并使用 szName
if (cbName < MAX_NAME) strncpy(szBuff,szName,MAX_NAME-1);
}
然而,您不能想当然地信任 cbName。攻击者可以设置该名称和缓冲区大小,因此必须进行检查!
void Function(char *szName, DWORD cbName) {
char szBuff[MAX_NAME];
#ifdef _DEBUG
// 探测
memset(szBuff, 0x42, cbName);
#endif
// 复制并使用 szName
if (cbName < MAX_NAME) strncpy(szBuff,szName,MAX_NAME-1);
}
// 复制并使用 szName
if (cbName < MAX_NAME) strncpy(szBuff,szName,MAX_NAME-1);
}
然而,您不能想当然地信任 cbName。攻击者可以设置该名称和缓冲区大小,因此必须进行检查!
void Function(char *szName, DWORD cbName) {
char szBuff[MAX_NAME];
#ifdef _DEBUG
// 探测
memset(szBuff, 0x42, cbName);
#endif
// 复制并使用 szName
if (cbName < MAX_NAME) strncpy(szBuff,szName,MAX_NAME-1);
}
注意:只能在调试版中这样做,以便在测试过程中捕获缓冲区溢出。
void Function(char *szName) {
char szBuff[MAX_NAME];
if(strlen(szName) >= MAX_NAME || strlen(szName)<0) { /* Do something appropriate, such as throw an error. */
}
else {
strncpy(szBuff,szName,MAX_NAME-1);
}
}
char szBuff[MAX_NAME];
if(strlen(szName) >= MAX_NAME || strlen(szName)<0) { /* Do something appropriate, such as throw an error. */
}
else {
strncpy(szBuff,szName,MAX_NAME-1);
}
}
完成同样目的的更容易方式是使用 strncpy() 库例程:
strncpy(dst, src, dst_size-1);
dst[dst_size-1] = '0'; /* Always do this to be safe! */
dst[dst_size-1] = '0'; /* Always do this to be safe! */
如果 src 比 dst 大,则该函数不会抛出一个错误;当达到最
大尺寸时,它只是停止复制字符。注意上面调用 strncpy() 中的
-1。如果 src 比 dst 长,则那给我们留有空间,将一个空字符
放在 dst 数组的末尾。
大尺寸时,它只是停止复制字符。注意上面调用 strncpy() 中的
-1。如果 src 比 dst 长,则那给我们留有空间,将一个空字符
放在 dst 数组的末尾。
Posted by
Jacob
at
8:46 AM
0
comments
Labels: IT, Programming DiggIt!
Thursday, November 30, 2006
Wii you would like to play!
Wii tech make everyone to take apart in the game and it enlarges people's imagination. How to let me refuse this FANTASTIC PLAY and so do you!
Posted by
Jacob
at
8:05 PM
0
comments
Thursday, November 23, 2006
That is why we call underground music! Cool!
These are Cool: U2 singer motion, audience's fantasy choral society, high flash light, soft prelude, hard snarl! All things in the stadium reveal what the UNDERGROUND music is, and that's called for COOL!!!
PS: The Bass is my favorite!
Posted by
Jacob
at
1:08 PM
0
comments
Subscribe to:
Posts (Atom)
