2013-12-10 73 views
2

我具有以下功能:爲結構指針運算給出奇怪結果

void deleteInventory(struct book** inventory) 
{ 
    struct book* ptr = NULL; 
    ptr = *inventory; 

    while(length != 0) 
    { 
     free(ptr); 
     length--; 
     ++ptr; 
    } 
    free(inventory); 
} 

結構:

結構的總大小:147字節(11 + 64 + 64 + 4 + 4) sizeof(結構體書)返回:148字節

我的庫存變量文件是結構的陣列,並且包含3個記錄

現在,在功能調試的結果(沒有高2個字節的地址):

inventory[0] = 0x1350 
inventory[1] = 0x14e0 
inventory[2] = 0x1670 

差異存儲器:400個字節,行

在第一迭代一切都OK了,第一條記錄刪除沒有問題

但經過

++ptr; 

PTR將包含:0x13e4

庫存[0] - PTR = 148個字節 - 根據結構的尺寸

,但它不是指下一個記錄正確區別,因爲下一個記錄的地址在內存中:0x14e0和我越來越腐敗的堆。

任何建議:爲什麼?

+2

在'deleteInventory'中,'length'變量在您使用時未初始化。 – lurker

+0

你可能已經完成了關閉第二個指針的指針運算。 - 只有建議。有像特殊的malloc庫和valgrind這樣的工具可以指出你的問題。編輯:@mbratch看起來有一個解決方案,除非長度是一個全局變量。 +1 –

+0

@mbratch'長度'是全局變量:) – pydevd

回答

6

我想你是從inventory錯誤地刪除。在free(ptr)之後,ptr之後的下一個內存塊可能會是垃圾內存。在這裏,我認爲是刪除您的庫存的正確方法:

void deleteInventory(struct book** inventory) 
{ 
    book** i = inventory; 
    while(length != 0) 
    { 
     free(*i); 
     length--; 
     ++i;//notice the difference (++i) instead of (++(*i)) 
    } 
    free(inventory); 
} 
+0

'++ i'會增加指針指針。不是所需的行爲。 –

+0

嘿,這個解決方案的工作原理 – pydevd

+1

它的工作原理是,它不是一個結構數組,而是一個指向結構體的指針數組。 –

7

你說inventory是一個數組,這很好。

你說過book佔用了148個字節(當你計算填充時),這很好。

你還沒有說的是你放在inventory中的指針是一次性分配的,而且你有一個指針數組的事實意味着它們不是。

但是,您創建book的每個,它似乎是動態的。不能保證這些書是連續的,只是指向它們的指針。

更改功能:

void deleteInventory(struct book** inventory) 
{ 
    struct book* ptr = NULL; 
    for (int i = 0; i < length; ++i) { 
     ptr = inventory[i]; 
     free(ptr); 
    } 
    length = 0; 
    free(inventory); 
} 

這將讀取連續的指針-TO-book陣列刪除所有book S,沒有假設bookš自己連續地分配。

+0

這是最簡單的解決方案,不感興趣! – pydevd

+0

@Oli查爾斯沃斯,主要目標是使用指針算術,而不是索引 – pydevd

2

我們只能推測inventory及其內容是如何生效的,但由於您單獨釋放了它們,因此您也可能單獨擁有它們。但是,您可以通過ptrptr++來查看它們,它假定連續分配的結構成員,就像您在數組中一樣。

然而,malloc()將以任何方式返回連續分配的連續存儲,沒有任何保證(並且平均實現也不會這樣做)。

這就是爲什麼你看到他們超過你期望的148字節。由於庫存可能是一個數組到分配的指針,你想要做的是:

while(length != 0) 
{ 
    free(*inventory); 
    length--; 
    ++inventory; 
} 
+0

而我將如何在庫存末尾釋放內存以用於'庫存'? – pydevd

+0

@ denis90:保持原樣,我只提到了關鍵部分,並沒有重寫整個程序。 – PlasmaHH

1

的指針算法不是問題......問題是你的陣列是如何佈局的假設是錯誤的。

我猜你不喜歡的東西:

length = 3; 
    inventory = (struct book**) malloc(sizeof(struct book *) * length); 
    ... 
    inventory[0] = (struct book*) malloc(sizeoof(struct book)); 
    inventory[1] = ... etc ; 

然後分配PTR盤點[0];

ptr = *inventory; 

但你認爲

++ptr == inventory[1]; 

,這是不正確的。