0

私は自分のプログラムの興味深い振る舞いをしています。最初にコードを表示することをお勧めします。

typedef struct PS {
    int num;
} PR;

typedef struct PS* PN;

typedef struct {
    int num;
    int tmp;
} VD;

void F (PN VPtr)
{
    register VD* qVPtr = (VD*)VPtr;
    // if this is call #2
    // qVPtr->tmp already is 8 for VP arg
    // qVPtr->tmp already is 16 for VP1 arg

    switch(VPtr->num){
    case 0:
        qVPtr->tmp = 8;
    return;
    case 1:
        qVPtr->tmp = 16;
        return;
    }
}

int main()
{
    PN VP = NULL;
    VP = (PN)malloc(sizeof(PR));

    VP->num = 0;
    F (VP);

    PN VP1 = NULL;
    VP1 = (PN)malloc(sizeof(PR));

    VP1->num = 1;
    F (VP1);

    F (VP);     // call #2 with VP arg
    F (VP1);    // call #2 with VP1 arg

    return 0;
}

main関数VPでは、 andVP1については知りませんが、関数の引数によっては、の最後の値を取得することができます。qVPtrtmpVPtrFqVPtr->tmp

この可能性について詳しく説明していただけますか?

4

3 に答える 3

3

関数Fでは、未定義の動作である未割り当てのメモリに書き込みます。悪いことや奇妙なこと起こります。

于 2012-11-29T11:14:18.033 に答える
2

F の動作に奇妙な点はありません。ポインター VPtr を VD 構造体へのポインターと見なすように指示した場合、VPtr で始まるメモリは、VD オブジェクトが存在しないにもかかわらず、VD 構造体オブジェクトを含むメモリと見なされます。PR と VD の両方の構造体が同じサイズの整数フィールドで始まるため、「魔法」が表示されます。しかし、メモリの次の部分は割り当てられていません。つまり、システムはそれを使って好きなことを行うことができ、そこに書き込むと足を撃つことができます。

于 2012-11-29T11:29:33.127 に答える
0

割り当てられたメモリ ブロックの末尾を超えて書き込みを行っているだけです。十分に小さいため、割り当てられていない仮想メモリ領域にヒットする可能性は低く、したがって、セグメンテーション エラーが発生することはありません。しかし、次のようなメモリ チェッカーでプログラムを実行しvalgrind、出力をお楽しみください。

==624== Invalid write of size 4
==624==    at 0x4004E2: F (pr.c:23)
==624==    by 0x400529: main (pr.c:37)
==624==  Address 0x4c38044 is 0 bytes after a block of size 4 alloc'd
==624==    at 0x4A05FDE: malloc (vg_replace_malloc.c:236)
==624==    by 0x40050F: main (pr.c:34)
==624==
==624== Invalid write of size 4
==624==    at 0x4004EB: F (pr.c:26)
==624==    by 0x400555: main (pr.c:43)
==624==  Address 0x4c38094 is 0 bytes after a block of size 4 alloc'd
==624==    at 0x4A05FDE: malloc (vg_replace_malloc.c:236)
==624==    by 0x40053B: main (pr.c:40)
==624==
==624== Invalid write of size 4
==624==    at 0x4004E2: F (pr.c:23)
==624==    by 0x400561: main (pr.c:45)
==624==  Address 0x4c38044 is 0 bytes after a block of size 4 alloc'd
==624==    at 0x4A05FDE: malloc (vg_replace_malloc.c:236)
==624==    by 0x40050F: main (pr.c:34)
==624==
==624== Invalid write of size 4
==624==    at 0x4004EB: F (pr.c:26)
==624==    by 0x40056D: main (pr.c:46)
==624==  Address 0x4c38094 is 0 bytes after a block of size 4 alloc'd
==624==    at 0x4A05FDE: malloc (vg_replace_malloc.c:236)
==624==    by 0x40053B: main (pr.c:40)
于 2012-11-29T11:20:55.970 に答える