当然有必要检查某些操作是否按预期发生:对malloc
, fopen
, fgetc
的调用
然而,有时添加这些检查会使代码太长——特别是对于非常简单的函数。例如,我有一个函数,我必须打开一个文件,读入几个参数,并分配与刚刚读入的内容相对应的内存。
因此,代码最终看起来像这样:- 打开文件
- 检查文件是否打开 读取参数
- 检查文件EOF是否未被读取(如果是,文件格式不正确)
- 检查内存分配是否按预期进行
等。
这里似乎有很多冗余。至少对于我的简单程序,如果上面的任何一个检查文件,我只是报告错误并将控制权返回给操作系统。代码最终看起来像这样:
if(filePointer == NULL){
perror("Error X occured");
exit(EXIT_FAILURE);
}
因此,由于这种错误检查,一个简单的几行函数可能会变成20行或更多行。是否有一些地方可以汇总这些错误的决定?
只是想知道是否有什么我错过了。
编辑:例如,当某些事件发生时,是否有一种方法可以中断程序流?例如,如果EOF被提前读取,那么跳转到某个函数通知用户(类似嵌入式系统中的中断)。
这是每个C程序员在他/她的职业生涯中的某个时刻都会问的问题。您是正确的,代码的某些部分将比实际有用的生产代码拥有更多的错误处理代码行。我过去用来简化错误处理的一种技术是实现一个错误函数,就像这样
static FILE *fpin = NULL;
static FILE *fpout = NULL;
static BYTE *buffer = NULL;
static void error( char *msg, char *name )
{
if ( msg != NULL )
{
if ( name != NULL )
fprintf( stderr, "%s: %sn", msg, name );
else
fprintf( stderr, "%sn", msg );
}
if ( fpin != NULL )
fclose( fpin );
if ( fpout != NULL )
fclose( fpout );
if ( buffer != NULL )
free( buffer );
exit( 1 );
}
然后像这样使用
void main( int argc, char *argv[] )
{
if ( argc != 3 )
error( "Usage: ChangeBmp infile outfile" );
if ( (fpin = fopen( argv[1], "rb" )) == NULL )
error( "Unable to open input file", argv[1] );
if ( (fpout = fopen( argv[2], "wb" )) == NULL )
error( "Unable to open output file", argv[2] );
size = sizeof( bmphead );
if ( fread( &bmphead, 1, size, fpin ) != size )
error( "Unable to read header", NULL );
size = sizeof( bmpinfo );
if ( fread( &bmpinfo, 1, size, fpin ) != size )
error( "Unable to read info", NULL );
当然,这只有在error函数可以访问所有必要的变量时才有效。对于简单的单文件程序,我只是将必要的变量设为全局变量。在较大的项目中,您可能需要更仔细地管理变量。
解决这个问题的一个常见方法,至少可以减少明显的代码大小,是用宏包装各种检查:例如,
#define CHECK_NULL(expr) {
if ((expr) == NULL) {
perror("Error X");
exit(-1);
}
}
CHECK_NULL(p = malloc(size))
CHECK_NULL(filePointer = fopen("foo.txt", "r"))
至于中断控制流,其他语言经常使用异常,这在c中也是可能的。然而,这往往是特定于平台的,并且在c中通常不是这样做的。