2017-03-29 4 views
0

私はCで単純なツリー構造を実装しています。プログラムはいくつかの奇妙な動作を示し、メモリ位置に値が格納された場所に絞り込むことができました。ポインタを使用してアクセスすると予期せず変更されます。それは再現可能ですが、再帰関数のいくつかの実行(入力に決定論的に依存する)の後にのみ発生します。それは 'while'ステートメントのヘッダーのどこかにあります。私は、 'while'の直前に、すべてのポインタが、予期され、明確に定義された内容のメモリセルを指していることを確認しました。私が最も気にしているのは、値のコピーを別の変数に代入しても変数が変わることです。私はそれが可能であるかどうか分かりませんが、私には明らかなものがあります。以下は、関連するコードの断片です。C初期化された変数の値は、比較後に単独で変更されます

typedef struct _Node { 
    int root; 
    struct _Node *children; 
    struct _Node *next; 
    struct _Node *previous; 
} Node; 

int delete_subtree_aux(Node *n) { 

    Node *children = get_children(n); 

    int i = children->root; 
    int j = i; 

    // At this point i and j both equal e.g. -4 

    while (!(children->next->root == children->root)) { 

     i = children->root; 

     // At this point i equals -3 

     assert(i == j); 

     // And j equals -3 too! 

     delete_subtree_aux(get_first(children)); 

    } 

    free_node(children); 
} 

すべてのサポートをよろしくお願いいたします。

編集:

free_node(children);で追加のブレークポイントを設定した後、私は何かが実行された命令の順番でオフになっていることに気づきました。一度にプログラムはfree_node(children);からwhile状態チェックをバイパスしてループの内側にまっすぐに進みます。 「n」、「i」、「j」および「children」は一緒に変化し、異なる機能入力に対応する。データブレークポイントを設定すると、異なる 'j'が2つの異なるメモリアドレスにあることが明らかになりました。

何らかの理由で、この関数のいくつかのインスタンスがパラレルで何らかの形で実行されているようですが、それは私の意図ではありません。私のフォローアップの質問は、エラーを引き起こすような状況でメモリを解放することができますか?はいの場合は、修正するために何をすべきですか?

編集2:上記のコードで呼ばれる他の機能のため 出典:

int free_node(Node *n) { 
    free(n); 
} 

Node *get_children(Node *n) { 
    return n->children; 
} 

Node *get_first(Node *list) { 
    return list->next; 
} 
+0

デバッガでプログラムを実行し、変数「j」に関連付けられたウォッチポイントを設定します。デバッガは 'j'の値が変わるとプログラムを停止します。少なくともあなたはプログラムのどの行が変更の責任を負っているかを知るでしょう。私はそれが 'assert'ではないと確信しています。 – DyZ

+0

もちろんそれは主張していません。前に述べたように、jを変更する行はwhile文のヘッダーです(while(!(children-> next-> root == children-> root)){') – Tomasz

+0

これはおそらくその行ではありません。したがって、デバッガを実行します。 – DyZ

答えて

0

問題はget_first(children) == get_last(children) whileループは、その最後の繰り返しを持っている必要がある場合ということでした。ただし、delete_subtree_auxは、children->nextが指す場所では更新できません。このアドレスにあるノードのchildrenがフリーである場合、whileループは停止する代わりに、children->nextNodeのようなゴミを指しているので、もう1回反復を試みます(childrenとは異なります)。しかし今度は、フリーのchildrenにアクセスしようとしていますが、もちろんエラーになります。

whileとその前の間の 'i'、 'j'、 'children'、 'n'の不思議な変化は、@Holsetyによって指摘されているようにスタック上に異なるレベルの再帰関数を見た結果でした。コメント。

関連する問題