9

次のコードは正常に機能します。

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

int main()
{
    struct node{
        int a, b, c, d, e;
    };
    struct node *ptr = NULL;
    printf("Size of pointer ptr is %lu bytes\n",sizeof (ptr));
    printf("Size of struct node is %lu bytes\n",sizeof (struct node));
    ptr = (struct node*)malloc(sizeof (ptr));               //Line 1
//    ptr = (struct node*)malloc(sizeof (struct node));    //Line 2

    ptr->a = 1; ptr->b = 2; ptr->c = 3; ptr->d = 4; ptr->e = 5;
    printf("a: %d, b: %d, c: %d, d: %d, e: %d\n",
            ptr->a,ptr->b,ptr->c,ptr->d,ptr->e);
    return 0;
}

次のように準拠した場合:

gcc -Wall file.c

私の質問は:なぜこれでいいのですか?

malloc引数で指定されたバイト数を割り当てます。これが私sizeof ptrの64ビットLinuxマシンの8バイトです。私は8バイトを提供すると思いmallocましたが、それではどのようにしてすべての変数a、b、c、d、eにアクセスしますか?それはgccだけでしょうか、それとも標準Cで何かが足りないのでしょうか?

私の知る限り、「Line1」の代わりに「Line2」があるはずですが、どちらの行も問題なく動作します。なんで?

4

4 に答える 4

11

ここでは未定義の動作があります。

malloc(あなたが言うように)8バイトを割り当てますが、このキャストは「悪い」です:

ptr = (struct node*)malloc(sizeof (ptr));

この行の後、ptrは8バイトしか割り当てられていないメモリブロックを指し、残りはいくつかの「ランダム」バイトです。だから、作る

ptr->a = 1; ptr->b = 2; ptr->c = 3; ptr->d = 4; ptr->e = 5;

によって割り当てられたメモリだけでなく、実際にメモリを変更しmallocます。

言い換えれば、あなたは記憶を書き直しているのであり、触れるべきではありません。

于 2012-07-31T17:10:44.680 に答える
8

1行目は正しくなく、十分なスペースが割り当てられません。後で構造体メンバーにアクセスできる場合、それはCが自分に属していないメモリへのアクセスを妨げるものではないからです。

ptr->b構造全体に十分なスペースを割り当てていないときに、などにアクセスptr-cすることは未定義の動作であり、次にコードを実行するとクラッシュしたり、プログラムの別の部分のデータを上書きしたりする可能性があります。

struct node問題を示すために、最初の直後に2番目を割り当てます。これは問題を示すことを保証するものではありませんが、次のような結果が表示される可能性があります。

struct node *ptr = NULL;
struct node *ptr2 = NULL;

ptr = (struct node*)malloc(sizeof (ptr));  // Your Line 1
ptr2 = malloc(sizeof(struct node));        // alloc another struct on the heap

ptr->a = 1; ptr->b = 2; ptr->c = 3; ptr->d = 4; ptr->e = 5;
ptr2->a = 11; ptr->b = 12; ptr->c = 13; ptr->d = 14; ptr->e = 15;

printf("ptr:  a: %d, b: %d, c: %d, d: %d, e: %d\n",
        ptr->a, ptr->b, ptr->c, ptr->d, ptr->e);
printf("ptr2: a: %d, b: %d, c: %d, d: %d, e: %d\n",
        ptr2->a, ptr2->b, ptr2->c, ptr2->d, ptr2->e);

出力:

ptr:  a: 1, b: 2, c: 3, d: 4, e: 11
ptr2: a: 11, b: 12, c: 13, d: 14, e: 15

ptr->eへの割り当てによって変更されていることに注意してください。これにより、ptr2->a不適切に割り当てられた1つの構造が別の構造のメモリを踏んでいることがわかります。これは確かにあなたが望むものではありません。

于 2012-07-31T17:10:22.917 に答える
3

mallocは8バイトしか割り当てていませんが、それ以上のメモリへのアクセスを停止することはありません。おそらくヒープが破損し、他のオブジェクトを上書きする可能性があります。プログラムの動作は未定義です。

于 2012-07-31T17:11:06.313 に答える
2

あなたはptr->a = 1; ptr->b = 2; ptr->c = 3; ptr->d = 4; ptr->e = 5;mallocによって割り当てられたメモリを超えてアクセスしています。
これはバッファオーバーフローの場合であり、を引き起こしundefined behaviourます。

それは可能です

 C and C++ provide no built-in protection against accessing or overwriting data
in any part of memory.

そのため、いつかは機能するかもしれませんし、プログラムをクラッシュさせるかもしれません。

于 2012-07-31T17:12:00.183 に答える