在C中清除错误处理方法

时间:2012-04-07 02:29:36

标签: c error-handling

我正在编写一个需要良好错误处理的C程序。代码喜欢这样:

If(doWork("A")<0){
    return -1;   
}
If(doWork("B")<0){
    undoWork("A");
    return -1;
}
If(doWork("C")<0){
    undoWork("A");
    undoWork("B");
    return -1;
}
return 0;

此代码有效但看起来非常混乱,尤其是我有一长串doWork(X)要调用。在这种情况下,是否有更好更清晰的方法来处理错误?

6 个答案:

答案 0 :(得分:7)

有些人,尤其是初级到中级程序员,对于在生产代码中看到goto有一种非常特殊的反应,但顺序获取资源的常用习惯用法及其出错时的智能释放如下: / p>

if(doWork("A") < 0)
  goto errA;

if(doWork("B") < 0)
  goto errB;

if(doWork("C") < 0)
  goto errC;

/* success! */
return 0;

/* Error handling / releasing resources section */
errC:
  undoWork("B");
errB:
  undoWork("A");
errA:

return -1;

您会在系统代码中看到大量示例,例如:在linux内核中。

答案 1 :(得分:1)

作为相同的任务doWork,您可以定义jobs的链接列表或向量,并将其作为参数传递给doWork,将相应的信息附加到此列表中功能,只需拨打undoWork一次:

If(doWork("A", &jobs)<0){
    return -1;   
}
If(doWork("B", &jobs)<0){
    undoWork(jobs);
    return -1;
}
If(doWork("C", &jobs)<0){
    undoWork(jobs);
    return -1;
}
return 0;

这样,无论工作组合被撤消,你的逻辑都不会变得过于复杂。

与@ twain249的解决方案相比,优势在于该功能决定是否将作业添加到列表中,因此您可以获得良好的隔离,模块化。

您当然可以将某种形式的可互换数据结构与此相结合,以进一步减少重复代码的数量

for(i=0; i < jobdata.size; i++) {
    If(doWork(jobdata[i], &jobs)<0){
        undowork(jobs);
        return -1;   
    }
}

正如您所注意到的,数据结构设计在算法设计中起着重要作用,通常比通常认为的要重要得多。

可能有成千上万的工作,代码将保持四行。

答案 2 :(得分:0)

可能不是。像C ++和C#这样的新语言支持异常,以帮助改善这种情况。

也许你可以有一个表格,以某种方式表明你已经完成了哪些任务并撤消了这些任务。但我真的认为这会使你的代码更复杂而不是更少。

另请注意,尽管使用goto有一些非常强烈的感觉,但事实上有时可以简化这样的结构。

答案 3 :(得分:0)

如果可以存储您必须在数组中调用doWork的所有内容,那么您可以显着缩短代码。

int i = 0;
int len = MAX_NUM; //set to the value of calls
int error = 0;

for(i = 0; i < len; i++) {
    if(doWork(a[i]) < 0) {
        error = 1;
        break;
    }
}

if(error) {
    for(int j = 0; j < i; i++) {
        undoWork(a[j]);
    }
    return -1;
}

答案 4 :(得分:0)

如果您没有超长列表,可以这样处理。

if (dowork("A") >=0) {
if (dowork("B") >=0) {
if (dowork("C") >=0) {
if (dowork("D") >=0) return 0;
undowork("C"); }
undowork("B"); }
undowork("A"); }
return -1;

答案 5 :(得分:0)

还有一种基于单通道循环的广泛使用的方法,该方法是明确的并且不需要goto。这意味着撤销功能正确处理已完成的工作和未执行的工作。

do
{
  if(doWork("A")<0)
    break;   

  if(doWork("B")<0)
    break;

  if(doWork("C")<0)
    break;

  return 0;
}
while(0);

undoWork("A");
undoWork("B");
undoWork("C");
return -1;