- Validating Function Input
在函数设计的时候,对传入的参数进行检测是一直都推荐的。例如、如果你设计的函数是公共API的一部分,它可能被外部客户端调用,这样很难保证客户端传进入的参数就是正确的。
例如,让我们来看看这个hypotethical DrawVehicle() 函数,它可以根据不同的质量来绘制一辆跑车,这个质量数值(nDrawingQaulity )是0~100。prcDraw 定义这辆跑车的轮廓区域。
看看下面代码,注意观察我们是如何在使用函数参数之前进行参数检测:
BOOL DrawVehicle(HWND hWnd, LPRECT prcDraw, int nDrawingQuality)
{
// Check that window is valid
if(!IsWindow(hWnd))
return FALSE;
// Check that drawing rect is valid
if(prcDraw==NULL)
return FALSE;
// Check drawing quality is valid
if(nDrawingQuality<0 || nDrawingQuality>100)
return FALSE;
// Now it's safe to draw the vehicle
// ...
return TRUE;
}
- Validating Pointers
在指针使用之前,不检测是非常普遍的,这个可以说是我们引起软件崩溃最有可能的原因。如果你用一个指针,这个指针刚好是NULL,那么你的程序在运行时,将报出异常。
CVehicle* pVehicle = GetCurrentVehicle();
// Validate pointer
if(pVehicle==NULL)
{
// Invalid pointer, do not use it!
return FALSE;
}
- Initializing Function Output
如果你的函数创建了一个对象,并要将它作为函数的返回参数。那么记得在使用之前把他复制为NULL。如不然,这个函数的调用者将使用这个无效的指针,进而一起程序错误。如下错误代码:
int CreateVehicle(CVehicle** ppVehicle)
{
if(CanCreateVehicle())
{
*ppVehicle = new CVehicle();
return 1;
}
// If CanCreateVehicle() returns FALSE,
// the pointer to *ppVehcile would never be set!
return 0;
}
正确的代码如下;
int CreateVehicle(CVehicle** ppVehicle)
{
// First initialize the output parameter with NULL
*ppVehicle = NULL;
if(CanCreateVehicle())
{
*ppVehicle = new CVehicle();
return 1;
}
return 0;
}
- Cleaning Up Pointers to Deleted Objects
在内存释放之后,无比将指针复制为NULL。这样可以确保程序的没有那个地方会再使用无效指针。其实就是,访问一个已经被删除的对象地址,将引起程序异常。如下代码展示如何清除一个指针指向的对象:
// Create object
CVehicle* pVehicle = new CVehicle();
delete pVehicle; // Free pointer
pVehicle = NULL; // Set pointer with NULL