C++ 有趣的行为使用铸造结构

C++ 有趣的行为使用铸造结构,c++,c,C++,C,我的程序有一个有趣的行为。最好先显示代码 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

我的程序有一个有趣的行为。最好先显示代码

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;
}
在主函数
VP
VP1
中,不知道
qVPtr
tmp
字段,但根据
F
函数中的
VPtr
参数,可以获得
qVPtr->tmp
的最后一个值


您能详细解释一下这种可能性吗?

在函数
F
中,您写入未分配的内存,这是一种未定义的行为。坏的和奇怪的事情会发生。

在函数
F
中,您写入未分配的内存,这是未定义的行为。坏的和奇怪的事情会发生。

您只是在写入已分配内存块的末尾。它足够小,因此命中未分配虚拟内存区域的可能性很低,因此不会出现分段错误。但在内存检查器中运行程序,如
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)

您只需在已分配内存块的末尾写入。它足够小,因此命中未分配虚拟内存区域的可能性很低,因此不会出现分段错误。但在内存检查器中运行程序,如
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)

f行为没有什么奇怪的——如果你告诉它考虑指针。 VPtr作为指向VD struct的指针,它考虑内存,从VPtr开始作为包含VD struct对象的内存,尽管那里没有任何VD对象。您的“魔力”出现是因为结构PR和VD都以相同大小的整数字段开始。
但内存的下一部分是未分配的,这意味着系统可以用它做任何它想做的事情,当你们在那个里写的时候,你们可以在你们的腿上开枪