0

私は明らかにここでprintfを非難していません、おそらく私のmemの割り当てとアクセスを台無しにしましたが、どこで間違ったのか理解できません。mainの2番目のprintfでプログラムがクラッシュします。2番目のものにコメントすると、3番目にもクラッシュします。実際、最初のprintfの後でpにアクセスするたびにクラッシュします!

誰かが私が間違っていることを説明できますか?

どうもありがとう。

typedef struct 
{
    char * firstname;
    char * lastname;
    int age;
} person;

person * new_person(char * firstname, char * lastname, int age)
{
    person p;
    int lf = strlen(firstname);
    int ll = strlen(lastname);
    p.firstname = (char *)malloc(++lf * sizeof(char));
    p.lastname = (char *)malloc(++ll * sizeof(char));
    strcpy(p.firstname, firstname);
    strcpy(p.lastname, lastname);
    p.age = age;

    return &p;
}    

int main()
{
    person * p = new_person("firstname", "last", 28);

    printf("nom : %s ; prenom : %s ; age : %d\n", p->lastname, p->firstname, p->age);
    printf("nom : %s ; prenom : %s ; age : %d\n", p->lastname, p->firstname, p->age);

    printf("nom : %s ; prenom : %s ; age : %d\n", (*p).lastname, (*p).firstname,(*p).age);

    return 0;
}
4

4 に答える 4

5

ローカル変数のアドレスを返しています。

new_person引数(人へのポインタ)を取るようにを変更するかmalloc、関数内で引数を取り、それを操作することができます。

関数で宣言した人は、関数が戻るとスコープから外れます。その後に起こることはすべて未定義です。偶然にもしばらくの間その値を維持するかもしれませんが、これに依存するべきではありません。printfを呼び出すと、スタックが大きくなり、人の古い場所が新しいもので上書きされます。

于 2012-09-06T19:51:25.787 に答える
3

問題は次の行にあると思います。

return &p;

ローカル変数へのポインタを返していることに注意してください。関数が戻るとすぐにローカル変数pが存在しなくなるため、これにより未定義の動作が発生します。その結果、そのポインターの読み取りまたは書き込みは、ガベージデータの読み取りまたは書き込みを行います。

これがすぐにクラッシュしないという事実は、コンパイラがコードを生成する方法のアーティファクトです。初めて電話をかけるとprintf、以前に使用されていたスペースがp、偶然の一致でうまく機能するように再利用される可能性があります。ただし、関数が戻った後、そのスタックフレームはの古いメモリを破壊しましたp。その結果、への2番目の呼び出しprintfは、への呼び出しから残されたガベージデータを読み取るprintfため、クラッシュします。

(具体的には、パラメーターを渡すと、文字列へのポインターがスタックにコピーされるため、printf実行すると、おそらく元のポインターが破棄されますが、コピーが使用されます。2番目の呼び出しでは、期限切れのprintfスタックフレームからガベージポインターが読み込まれます。以前住んでいたのと同じ住所にp住んでいます。)

これを修正するpには、へのポインタに変更してから、personを使用mallocして割り当てることを検討してください。そうすれば、メモリは関数呼び出しを超えて持続するので、このクラッシュはなくなるはずです。

お役に立てれば!

于 2012-09-06T19:52:21.540 に答える
1
 person p;

// stuff

return &p

これは間違っています。関数が戻った後、ローカル変数はスコープを離れます-そのアドレスは無効になります。ヒープに構造を割り当てる必要があります。

person *new_person(char *firstname, char *lastname, int age)
{
    person *p = malloc(sizeof(*p));
    p->firstname = strdup(firstname);
    p->lastname = strdup(lastname);
    p->age = age;

    return p;
}    
于 2012-09-06T19:52:38.280 に答える
0

問題は関数new_personにあります。スタックに人物pを作成し、そのアドレスを返します。person * p = new person(....。

于 2012-09-06T19:52:35.823 に答える