-2

このサンプルファイルがあります

example.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

typedef struct {
    char *name;
} player;

void
playercreation(player *p, int nr)
{
    p=malloc(sizeof(player));
    char stringtemp[10];
    printf("Create player %d:\nWrite your name (max 10 letters): ", nr);
    scanf("%s", stringtemp);
    p->name=malloc(sizeof(*(p->name))*11);
    strcpy(p->name, stringtemp);
    p->drawnlines=0;
    p->squares=0;
}

void
playercreationMenu(player *p1, player *p2)
{
    playercreation(p1, 1);
    playercreation(p2, 1);
}

void
confirmPlayer(player *p)
{
    printf("player %s created\n", p->name);
}

int
main(void)
{
    player p1, p2;
    playercreationMenu(&p1, &p2);
    confirmPlayer(&p1);
    confirmPlayer(&p2);
}

私の実際のプログラムでは、これは、プレーヤーが作成されないために存在しないプレーヤー構造内の何かにアクセスしようとしているため、セグメンテーション違反を引き起こしますが、この例では、プレーヤー名が(null)であるにもかかわらず、名前はplayercreationMenu関数で指定されました。どうしてこれなの?

4

4 に答える 4

3

count初期化されていません。ガベージインガベージアウト。

于 2012-11-08T18:11:45.080 に答える
2

あなたが書く

player p1, p2;
playercreationMenu(&p1, &p2);

しかし、コンストラクター関数では、

void playercreation(player *p, int nr)
{
    p = malloc(sizeof(player));

    ...
}

つまりmalloc()、すでに割り当てられている(スタック上にある!)構造体のアドレスを含むローカル変数にメモリの古いブロックを割り当てているのです...への呼び出しをドロップmalloc()すれば問題ありません。

countまた、変数を初期化する前、または変数に値を割り当てる前に、変数を使用しています。

int count;
...
p->name = malloc(sizeof(char) * (count + 1));

つまり、1つは未定義の動作、2つは非常にランダムな量のメモリ(境界を超えて書き込むことができる->別の未定義の動作)、または割り当てられるメモリが多すぎる場合はNULLポインタを取得することです。 (3番目の未定義の動作)。

1行に3つのUBがあります-クラッシュすることを期待してください。

于 2012-11-08T18:13:21.160 に答える
2

コードに次の2行の問題があります。

p=malloc(sizeof(player));
int count;

main()で宣言するときに、スタック上のプレーヤー構造にすでにスペースを割り当てているため、mallocは必要ありません。

カウントを初期化していないため、ガベージ値があります。countを使用してmallocを呼び出すと、任意の量のメモリを要求している可能性があります。

于 2012-11-08T18:15:52.617 に答える
1

count1つは、他の数人が指摘しているように、初期化することはありません。これは、それが任意の値であることを意味するため、何をに渡すのかわかりませんmalloc

scanfまた、誰かが10文字を超えて入力するとバッファがオーバーフローするため、おそらく使用しないでください。代わりにお勧めfgetsします。

さらに、最初にスタック上でプレーヤーを宣言し、それらへのポインターをに渡しますplayercreationMenu。それは結構です。次に、それらをに渡しますplayercreation。これも問題ありません。で、プレーヤーへのポインタを。から返されたポインタで上書きplayercreationします。したがって、でスタックに割り当てた元のに実際に何もすることはありません。mallocplayermain

Basileが示唆しているように、-Wallより多くのコンパイラ警告を取得するためにコンパイルして、それらに細心の注意を払うことをお勧めします。実際、私は好き-Wall -Wextra -Werrorです; -Wall実際にはすべての警告が表示されるわけではないので-Wextra、いくつかのより便利な警告をオンにし、-Werror警告をエラーに変えて、無視できないようにします。

于 2012-11-08T18:21:56.790 に答える