2012-11-29 25 views
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; 
} 

在主要功能VPVP1不知道qVPtrtmp場,但根據當地F功能VPtr參數有可能獲得的qVPtr->tmp最後一個值。

你能否詳細解釋這種可能性?

回答

2

沒有什麼奇怪的F中的行爲 - 如果你告訴它要考慮指針 的vptr的指針VD結構,它認爲內存,開始以VPtr作爲包含VD結構對象的內存,儘管這裏沒有任何VD對象。您的「魔術」出現,因爲結構PR和VD都以相同大小的整數字段開始。 但是下一部分內存是未分配的,這意味着系統可以隨它做任何事情,當你在那裏寫時,你可以在你的腿上拍攝。

3

在函數F中寫入未分配的內存,這是未定義的行爲。壞的和奇怪的事情發生。

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)