之前在学C语言时,被许多教程文章教导不要使用goto语句。诚然,滥用goto语句会导致程序逻辑混乱难以维护,但在某些情况下使用goto语句却会使程序更加简洁,代码结构更加清晰。在linux源码中就有大量的错误处理流程中使用了goto语句。今天要说的倒影式错误处理机制是在写linux驱动时常常用到的一个错误处理技巧。在碰到涉及资源释放的错误处理情况时十分好用。
下面随意选选了Linux源码中某段驱动代码:
int do_create_sysfs_files(void)
{
struct device_driver *sysfs = &st_template.gendrv;
int err;
//步骤1
err = driver_create_file(sysfs, &driver_attr_try_direct_io);
if (err) return err; //步骤1错误处理。第一步出错,没有资源需要释放,直接返回。
//步骤2
err = driver_create_file(sysfs, &driver_attr_fixed_buffer_size);
if (err) goto err_try_direct_io;
//步骤3
err = driver_create_file(sysfs, &driver_attr_max_sg_segs);
if (err) goto err_attr_fixed_buf;
//步骤4
err = driver_create_file(sysfs, &driver_attr_version);
if (err) goto err_attr_max_sg;
return 0;
//步骤4错误处理
err_attr_max_sg:
driver_remove_file(sysfs, &driver_attr_max_sg_segs);
//步骤3错误处理
err_attr_fixed_buf:
driver_remove_file(sysfs, &driver_attr_fixed_buffer_size);
//步骤2错误处理
err_try_direct_io:
driver_remove_file(sysfs, &driver_attr_try_direct_io);
return err;
}
上述代码中,代码流程按照 步骤1->步骤2->步骤3->步骤4 执行。而错误处理代码的书写顺序刚好相反,因而称为倒影式错误处理。
使用倒影式错误处理机制,可以避免在代码的正常执行流程中在if-else中写入过多切重复的错误处理代码。如果不使用倒影式错误处理机制,如果在步骤2中出现错误,则需要步骤2中的if (err)中释放步骤1成功申请的资源。同理,如果在步骤3中出现错误,则需在步骤3中的if (err)中释放步骤1和步骤2申请的资源,此时,释放步骤1资源的代码就重复了,主体流程代码也变得不简洁,随着主流程步骤增加,这会变得更加明显。而倒影式错误处理机制是将错误处理代码集中统一书写到函数末尾,代码清晰,简洁。