2

次のリンクリスト関数でバグが発生しましたが、どうしたらよいかわかりません。(私にとって)クレイジーな部分は、私のコードがこれまで完全に機能していて、バグが発生する前に数回の呼び出しで機能していることです。

この関数の目的は、PathItemのリンクリストの最後に新しいアイテム(BinaryItemを含むPathItem)を追加することです。私の機能は次のとおりです

void addPathItemAtEnd(struct PathItem * pathItem, struct BinaryItem * binaryItem) {
    if (pathItem == NULL) {
        pathItem = malloc(sizeof(struct PathItem));
        pathItem->binaryItem = binaryItem;
        pathItem->next = NULL;
    } else {
        while (pathItem->next != NULL) {
            pathItem = pathItem->next;
        }
        struct PathItem * newPathItem = malloc(sizeof(struct PathItem));
        newPathItem->binaryItem = binaryItem;
        newPathItem->next = NULL;
        pathItem->next = newPathItem;        
    }
}

問題のある行はpathItem->next = newPathItemです。EXC_BAD_ACCESSデバッガーでエラーが発生します。繰り返しになりますが、このコードは以前は正常に機能していたので、今何が起こっているのか理解できません...

これは、ポインタ変数の再割り当てに関する問題のようです。何が悪いのかわからない。

考え、提案、批判。必要に応じて、コードの残り/残りを添付できます。本当に事前にあなたの助けと感謝が必要です。

4

2 に答える 2

3

主な問題は、コピーpathItemとして渡され、変更が元のコードに反映されないようにすることです。Cは値渡しパラダイムを使用します(C ++も値渡しを使用しますが、少なくとも参照型があるため、Cの鈍いポインターメソッドをいじくり回す必要はありません)。

渡したポインタが最初はNULLである場合、戻ったときにNULLのままであるため、これがどのように機能したかはわかりません。つまり、リストは常に空です。pathItem

おそらくそれに対する最も簡単な修正は、プロトタイプを次のように変更することです。

void addPathItemAtEnd (struct PathItem *pPathItem, blah blah blah ...

次に、現在pathItemその関数内にある場合は、それを。に置き換えます(*pPathItem)

そしてもちろん、ポインタを使ってそれを呼び出し、次のように変更します。

addPathItemAtEnd (listStart, newItem);

に:

addPathItemAtEnd (&listStart, newItem);

余談ですが、堅牢なコードはからの戻り値をチェックし、mallocそれに応じて動作します。授業や小さな個人的なプロジェクトは失敗がないと仮定して逃げることができるかもしれませんが、それは現実の世界ではそれをカットしません:-)

于 2012-09-03T04:05:34.920 に答える
1

リストのルートを値で渡しているため、実際のルートは決して変更されません。変更できるように、代わりに &root を渡します。

struct PathItem *root = NULL;

void addPathItemAtEnd(struct PathItem **pRoot, struct BinaryItem * binaryItem) {
    // advance pRoot so that either it points to the original root or it
    // points at the next field of the last item
    while (*pRoot)
        pRoot = &(*pRoot)->next;
    // add the new item
    struct PathItem *p = malloc(sizeof(struct PathItem));
    // TODO check p!= NULL
    p->next = NULL;
    p->binaryItem = binaryItem;
    *pRoot = p;
}

のように呼ばれる

addPathItemAtEnd(&root, blah);
于 2012-09-03T04:23:01.413 に答える