0

我的程序出现了一个奇怪的分段错误。Dlist 是一个创建链接列表的类,该链接列表具有从动态列表中插入和删除项目的操作。我很肯定我的这个类的实现是正确的,但是这段代码正在产生一个段错误。奇怪的是,当我让我的 atleastTwo 和 atleastOne 函数通过引用传递时,段错误消失了,一切都编译了。任何人都可以阐明这个问题吗?

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

谢谢

4

3 回答 3

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";
  }
}

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

我希望它有所帮助。

于 2012-12-11T05:46:31.807 回答
0

如果您按值传递(不使用引用),那么您每次都有效地制作副本。究竟这如何令人困惑尚不清楚,您需要准确研究各种复制构造函数在做什么。但肯定是通过引用传递是你的意思吗?为什么要复制整个集合?

于 2012-12-11T05:15:21.607 回答
0

盯着你的 Dlist 实现代码看了半天(乍一看并没有错),我认为问题出在这里:

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

考虑到在那里执行的操作,在将(and )removeAll()初始化为 NULL 之前调用会导致不好的事情。firstlast

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

于 2012-12-11T06:10:41.833 回答