0

ここで本当に奇妙な問題が発生しています。誰かが私を助けてくれることを願っています。それがコードです。

Node *fct(Node *list)
{
  Node *node;
  node = list;
  ...
}

通常はすべてスムーズに実行されますが、ランダムなケースでセグメンテーション フォールトが発生します。GDBでデバッグしました。通常、リストとノードのアドレスは両方とも 0x80d4000 ですが、Segfault が発生すると、ノードのアドレス = 0x400 になります。(リストはまだ 0x80d4000 です)。
これがどこでうまくいかないのか、本当にわかりません。何かアイデアはありますか?

4

1 に答える 1

1

これは確かなコードではありませんが、どこかでアドレスのコピー(ポインター)を渡し、COPYに変更を加えた(mallocのように)と思われます。このアドレスのアドレス(ポインター上のポインター)を渡す代わりに、実際にはポインターを変更し、そのコピーの1つは変更しません。

私が話していることを説明するための例:

int dostuff(char* str)
{
    str = malloc(sizeof(char));
    str[0] = 0x42;
    return 1; // size of string.
}

int main(int argc, char** argv)
{
    char* mystr = NULL;
    unsigned int strlength = 0;
    strlength = dostuff(mystr);
    printf("%s\n", mystr);  // Segfaults here: mystr == NULL.
    free(mystr);
    return 0;
}

だからここに何が起こっているのですか:

  1. NULLに設定された新しいcharポインタを作成します(たとえば、再割り当てする場合に適しています)。
  2. その値(NULL)をに渡しますdostuff。この関数は、この値のコピーを(char *型で)作成し、このコピーを変更します。
  3. printfは印刷のためにmystrにアクセスし、NULL [0](0)から読み取ろうとしているときに、セグメンテーション違反を起こします。

mainもちろん、残りは実行されません。

誰かがその落とし穴に陥る理由は次のとおりです。通常、関数でポインタを使用して変更を行う場合は、アドレスではなくコンテンツを変更します。アドレスを変更すると、ほとんどの場合(このような場合を除いて)、新しいアドレスを返すようにアドレスを変更する関数があります。のようにaddress = malloc(size)

一方、POINTERを設定したい場合(明らかにコンテンツではない場合)、そのアドレスのコピーを関数に渡す必要があります。上記のコードの動作バージョンは次のとおりです。

int dostuff(char** str)
{
    (*str) = malloc(sizeof(char));
    (*str)[0] = 0x42;
    return 1; // size of string.
}

int main(int argc, char** argv)
{
    char* mystr = NULL;
    unsigned int strlength = 0;
    strlength = dostuff(&mystr);
    printf("%s\n", mystr);  // Now works: mystr is allocated.
    free(mystr);
    return 0;
}

したがって、覚えておいてください。疑わしい場合は、ポインタを返し、他の変数のアドレスを取得してください(strlengthここ)。不可能な場合は、操作しているデータの実際のタイプに十分注意し、変更後にアドレスを再確認してください。

お役に立てば幸いです。

于 2012-12-06T12:58:54.997 に答える