0

そのため、コードでセグフォルトが発生していますが、何が原因なのかわかりません。私が捕まえられなかった何かを捕まえることができる人はいますか?

論理的には、最後に物を連結して char 配列 (文字列) を作成し、それを文字列の配列に追加しようとしています。

最終的には、この「word1、word2、word3、word4、word5...など」のようになります。

セグメント障害が発生するstrcat(str, ", ");

void save_ladder(graphNode *curNode) {

    char *str = malloc(1000 * sizeof(char));

    strcpy(str, "");
    strcat(str, curNode->word);
    strcat(str, ", ");

    graphNode *prev = curNode->prevWord;
    while (prev != NULL) {
            if (prev->prevWord != NULL) {
                strcat(str, prev->word);
                strcat(str, ", "); // SEG FAULT HAPPENS HERE
            }
            else 
                strcat(str, prev->word);

            prev = prev->prevWord;
    }

    ladders[numLadders++] = str;
}

gdb スタックトレース:

Program received signal SIGSEGV, Segmentation fault.
0x00000000004013d1 in save_ladder (curNode=0x6420f0) at wordladder.c:150
150             strcat(str, ", ");

なぜこれが起こっているのか誰にも分かりますか?

4

3 に答える 3

3

おそらくバッファオーバーフローです。次のコードをwhileループのすぐ内側に入れて、そうであるかどうかを確認します。

printf ("%d %d\n", strlen (str), strlen (prev->word));

これら 2 つの数値の合計が 1000 近くになる場合は、おそらくバッファーを大きくする必要があります。

または、2 番目の値が少し大きい、または単語が多すぎるように見える場合は、リスト内のデータまたはリスト構造自体に問題があります。

さらに、他にも2点あります。sizeof(char)1つ目は、常に1であるため、乗算する必要がないことです(malloc失敗した場合に備えて、の戻り値も確認する必要があります)。

if2 つ目は、次のステートメントを使用せずに、文字列の構成を単純化できることですwhile

strcpy(str, curNode->word);
graphNode *prev = curNode->prevWord;
while (prev != NULL) {
    strcat (str, ", ");
    strcat(str, prev->word);
    prev = prev->prevWord;
}
于 2012-12-09T09:12:12.217 に答える
1

注意/コメント/返信することが2つあります。

  1. Painter の Schlemielのアルゴリズムを使用しています。すべてstrcat()の で、これまでに収集された文字列が再度トラバースされます。現在いる場所を指す「カーソルポインター」の使用を検討する必要があります。これまでの文字列の最後に設定するには、それぞれを a に置き換えてくださいstrcat(str, ...)。最初に設定する必要があります。strcpy(crsr, ...)crsr += strlen(crsr)crsrstr

  2. 他の人が書いたように、コードは最大 1000 文字でしか使用できません。ストラクタが壊れているか、文字列の 1 つが長すぎます。いずれにせよ、あなたのアルゴリズムは柔軟性に欠けます。追加する前にすべての文字列の長さを確認することを検討する必要があります。収まらない場合は、適切に調整しrealloc()てくださいstr。(あなたも更新することを忘れないでくださいcrsr。) この場合、もはや制限はありません。

    str最後にサイズを変更して、strlen(str) + 1メモリを無駄にしないようにします。

于 2012-12-09T09:24:11.923 に答える
1

バッファオーバーフローの回答に同意します。コードのクリーンアップにも同意します。ただし、asprintf や snprintf を調べる必要があるのではないかと思います。asprintf では、char ** を指定すると、新しい文字列の場所が返されます。これは、メモリを自分で慎重に管理する必要がない場合に非常に役立ちます。このルーチンも GNU 拡張であるため、注意してください。Snprintf では、char * と残りのバッファーの長さを渡して、残りのフォーマットが適合するかどうかを判断できます。これにより、オーバーフローがキャッチされます。

asprintf の使用例を次に示します。

char *output = NULL;
char *last = NULL;

prev = curNode;
while (prev != NULL) {
    last = output;
    if (asprintf(&output, "%s,", prev->word) < 0) {
        break;  // error
    }
    if (last != NULL)
        free(last);
    }
    prev = prev->prevWord;
}

// remove trailing ',' here

注: 上記のコードはテストされていません (タブレットで書いています)。

于 2012-12-09T13:42:25.563 に答える