3

課題のコードを書いているときに、1 つの奇妙な動作に固執してしまいました。コードは大きいので、不要ですが掲載しません。

ベクトルからオブジェクトを削除しようとしたときに、セグメンテーション違反が発生しました。自分でデバッグしようとしているときに、次のことがわかりました。

次のスニペットを使用してコードを実行すると、ベクターが空になり、2 行目でセグメンテーション違反が発生します (ベクターが空であるため)。

cout << this->adjacencyList.empty() << endl; // yeah, I'm working with graph
cout << *(this->adjacencyList[0]) << endl; // list has pointers

ただし、2行目を削除すると、ベクターが空ではないことが示され、次に進みます。空ベクトルのガードはそれを保持できず、セグメンテーション違反が発生します。

この行動について何か考えはありますか?ポイントがまだ曖昧な場合は、編集として完全なコードを投稿できます。

前もって感謝します。

編集:

「もう少し」とおっしゃっていた方へ。

void Node :: removeEdge (string destination) // removes an edge; edge is a class that contains a pointer to another node and its weight
{
    bool deleted = false;
    cout << *this << endl; // output stream operator is overloaded for node class and is working properly - shows it's label and edges - no error for an edge
    cout << this->adjacencyList.empty() << endl;
    // cout << *(this->adjacencyList[0]) << endl; // output stream operator is overloaded for edge class - error for an edge
    if (!this->adjacencyList.empty())
    {
        for (vector <Edge *> :: iterator itr = this->adjacencyList.begin(); itr != this->adjacencyList.end(); ++itr)
        {
            if (((*itr)->getAdjacent())->getLabel() == destination) // segfault here
            {
                Edge *temp = *itr;
                this->adjacencyList.erase (itr);
                delete temp;
                deleted = true;
            }
        }
    }
    if (!deleted)
        throw EDGE_DOES_NOT_EXIST; // one of exceptions declared in enum somewhere in my code
}

2番目の編集:

注: ヘッダーは変更できません (アシスタントから提供されたものです)。変更を求めないでください。

完全なコードに興味がある場合は、ここで見つけることができます

http://pastebin.com/iCYF6hdP - Exceptions.h - すべての例外

http://pastebin.com/1fcgHGDa - Edge.h - エッジ クラス宣言

http://pastebin.com/C2DD6e3D - Edge.cpp - エッジ クラスの実装

http://pastebin.com/ZNqQ1iHE - Node.h - ノード クラス宣言

http://pastebin.com/kaVtZ3SH - Node.cpp - ノード クラスの実装

http://pastebin.com/A7Fwsi4m - Network.h - グラフ クラスの宣言

http://pastebin.com/02LX0rjw - Network.cpp - グラフ クラスの実装

http://pastebin.com/MRMn0Scz - main.cpp - サンプル メイン

4

1 に答える 1

1

ベクトルの最初の要素に格納されているポインターが無効であると思います (おそらくNULL?)。

したがって、セグメンテーション違反は発生しませんthis->adjacencyList[0]が、*(some_invalid_pointer).

試す

Edge* firstEdge = this->adjacencyList[0];
cout << *firstEdge << endl;

これを確認します。

編集

最初のステートメント (代入) で segfault が発生した場合、これは、それthisが無効であるか、何らかの方法で の内部に属するメモリを破壊したことを意味しますvector。これを確認するには、あなたを扱うすべてのコードを確認する必要がありますadjacencyList(そして、SO の人々がこのタスクを実行する時間があるかどうかはわかりません...)

ノート

にバグが見つかりましたがremoveEdge、これはあなたの問題とは直接関係ありません。ループ内でvector::erase、現在の要素を削除するために使用します。これにより、現在の反復子を超えるすべての反復子が無効になるため、理論的には、ループの残りの部分は悪名高い「未定義の動作」(TM) になります。この特定のケース (および「通常の」標準ライブラリを想定) では、セグメンテーション違反は発生しませんが、いくつかの要素を見逃す可能性があります。

現在の要素を削除すると、現在の反復子 (通常は単純なポインター) が次の要素を指します。次に、ループのインクリメントにより、この要素の後の要素に移動され、1 つの要素がチェックされなくなります。

他の場所のコードに同様のバグがある場合、メモリの破損につながる可能性があります。

ヒント

Microsoft C++ を使用している場合は、チェック済み反復子を有効にできます(こちらを参照)。これらは、コード内のこの種のバグを発見できる可能性があります。

2回目の編集(コードに応じて)

に重大なエラーがありNode::operator+ます。

Node &operator+ (Node &l, Node &r) // merges two nodes - for network merging
{
Node newNode (l.label);
    // Doing something
return newNode;
}

つまり、ローカル変数への参照を返しているので、決してそうしないでください:) ...

個別に管理され、デストラクタで解放されるポインターのベクトルを使用しているため、署名を単に に変更することはできないことに注意してください。Node operator+(...この場合、標準のコピー コンストラクターが呼び出され、すべてのポインターが単純にコピーされます。結果オブジェクト。次に、ローカル オブジェクトのデストラクタが呼び出され、すべてのポインタが無効になります。

これを修正するNodeには、隣接リスト内のすべてのエッジの実際のコピーを作成するコピー コンストラクターを実装する必要があります。

または、リストにスマート ポインター (それぞれまたは) を使用することもできますauto_ptrunique_ptrshared_ptr

または、演算子Node::mergeFrom(Node& node2)をオーバーロードする代わりに、マージ関数を次のように変更します。+

元の問題に関しては、Node現在のコードを使用して無効なインスタンスに簡単に取り組んでしまう可能性があります (そのため、*this-Pointer は内部で無効になりますremoveEdge) 。

于 2013-05-16T19:07:41.520 に答える