0

プログラムで奇妙なセグメンテーション違反が発生しています。Dlist は、動的リストからアイテムを挿入および削除する操作を含むリンク リストを作成するクラスです。このクラスの実装は正しいと確信していますが、このコードはセグ フォールトを生成しています。奇妙な点は、atleastTwo 関数と aleastOne 関数を参照渡しにすると、セグ フォールトがなくなり、すべてがコンパイルされることです。誰でもこの問題に光を当てることができますか?

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 の変更は許可されていない可能性があります。不安定なコードと過度のテストを回避するための推奨される解決策は、次の提案です。オペランドの量をテストする代わりに、それを試して、処理メソッド内に例外ハンドラーを配置してください。この 2 番目の解決策の問題は、スタックが一貫性のない状態のままになる可能性があることです。つまり、計算を続行できず、最初からやり直す必要があります。

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

スタックのコピーを保持し、1 つのコピーで計算を行うことができます。この方法でパフォーマンスが大幅に向上し、コードが読みやすく理解しやすくなります。

お役に立てば幸いです。

于 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);
}

(および) を NULLremoveAll()に初期化する前に呼び出すと、そこで実行される操作を考えると、悪いことが起こります。firstlast

Dlist 設計のもう 1 つの問題は、生のポインターを保持している (トリッキーですが、必ずしも悪いわけではありません。ユーザーがそれらを削除する責任があることが誰にとっても明らかであると仮定すると) にもかかわらず、ディープ コピー メカニズムが実装されていることです。コンテンツを手動で削除しない限り、一時的な Dlist オブジェクトは、atLeastOneおよび関数に渡すコピーと同様にリークします。atLeastTwo

于 2012-12-11T06:10:41.833 に答える