C ++奇怪的分段错误

时间:2012-12-11 05:09:18

标签: c++ linked-list segmentation-fault

我的程序中出现了一个奇怪的分段错误。 Dlist是一个类,它创建一个链接列表,其中包含从动态列表中插入和删除项目的操作。我很肯定我这个类的实现是正确的,但是这段代码产生了一个seg错误。奇怪的是,当我使我的atleastTwo和atleastOne函数通过引用传递时,seg错误消失并且所有内容都会编译。任何人都可以解释这个问题吗?

bool atleastTwo(Dlist<double> stack){
try{
    stack.removeFront();
    stack.removeFront();
} catch(emptyList e){
    cout << "Not enough operands\n";
    return false;
}
return true;
}

bool atleastOne(Dlist<double> stack){
try{
    stack.removeFront();
} catch(emptyList e){
    cout << "Not enough operands\n";
    return false;
}
return true;
}

void processInput(inputs usrInput, Dlist<double> &stack){
switch(usrInput){
    case i_add:
        if(atleastTwo(stack)){doOperation(stack, add);}
        break;
    case i_subtract:
        if(atleastTwo(stack)){doOperation(stack, subtract);}
        break;
    case i_multiply:
        if(atleastTwo(stack)){doOperation(stack, multiply);}
        break;
    case i_divide:
        if(atleastTwo(stack)){doOperation(stack, divide);}
        break;
    case i_negation:
        if(atleastOne(stack))negation(stack);
        break;
    case i_duplicate:
        if(atleastOne(stack)){duplicate(stack);}
        break;
    case i_reverse:
        if(atleastTwo(stack)){reverse(stack);}
        break;
    case i_print:
        if(atleastOne(stack)){print(stack);}
        break;
    case i_clear:
        clear(stack);
        break;
    case i_printAll:
        printAll(stack);
        break;
    default:
        break;
}
}

T *removeFront();
// MODIFIES this
// EFFECTS removes and returns first object from non-empty list
//         throws an instance of emptyList if empty

由于

3 个答案:

答案 0 :(得分:1)

关于问题本身,我不知道你的代码会如何发生段错误。我怀疑问题出在Dlist的代码中,可能是一个糟糕的析构函数?

要解决您的问题,您可以在Dlist中实现元素计数并检查它。但也许你不允许修改Dlist。避免跳转代码和太多测试的首选解决方案将遵循建议。而不是测试操作数的数量,只需尝试它,并将异常处理程序放在您的处理方法中。第二个解决方案的问题是堆栈可能保持不一致状态:这意味着您无法继续计算并应从头开始重新启动。

void processInput(inputs usrInput, Dlist<double> &stack)
{
  try{
    // .... your old code WITHOUT ifs
  } catch(emptyList e){
    cout << "Not enough operands\n";
  }
}

我认为后者是一种方法,您可以保留堆栈的副本并在一个副本上进行计算。这种方式的性能会更好,代码更易于阅读和理解。

我希望它有所帮助。

答案 1 :(得分:0)

如果您通过值(不使用引用),则每次都有效地复制。究竟如何令人困惑的东西还不清楚,你需要准确研究各种拷贝构造器正在做什么。但肯定通过引用传递你的意思是什么?你为什么要复制整个系列?

答案 2 :(得分:0)

在盯着你的Dlist实现代码很长一段时间(乍一看看起来不错),我认为问题在于:

template <typename T>
Dlist<T>::Dlist(const Dlist &l){
    removeAll();
    copyAll(l);
}

在将removeAll()(和first)初始化为NULL之前调用last将导致错误的事情,因为在那里执行了操作。

Dlist设计的另一个问题是你持有原始指针(这很棘手但不一定是坏的,假设每个人都清楚用户负责删除它们),但你已经实现了深层复制机制。除非您手动删除其内容,否则临时Dlist对象将泄漏,您传递给atLeastOneatLeastTwo函数的副本也将泄漏。