2012-01-20 63 views
0

這是一個廉價的黑客,但我想改變我正在處理的C庫的分配方法。出於某種原因,它使用了GlobalLock,可能是因爲它曾經是多個DLL。我已經把它改爲頁頭:更新C庫,獲得堆腐敗

HANDLE BmiDibAlloc(size_t uBytes) 
{ 
    HANDLE alloc = malloc(uBytes + sizeof (size_t)); 

    if (alloc != NULL) 
    { 
     memcpy_s(alloc, sizeof (alloc), &uBytes, sizeof (size_t)); 
    } 

    return BmiDibAttach(alloc); //just tracks the number of memory allocs for logging 
} 

BOOL BmiDibFree(HANDLE hdib) 
{ 
    if (!hdib) { 
     return TRUE; 
    } 
    free(hdib); 
    // Forget this handle: 
    return BmiDibDetach(hdib); 
} 

既然不能使用GlobalSize了我釘在第一的sizeof(爲size_t)字節分配的大小...

時對位圖寫入罰款後分配用第一種方法 - 但是,當我到Free時拋出一個堆腐敗。授予它可能在這些電話之間的某個地方,有沒有人看到與給出的信息有關的錯誤?

+2

你的代碼看起來很好,可能問題出在代碼的其餘部分;我認爲唯一的錯誤是sizeof(alloc)'錯誤,它應該是'sizeof(size_t)'(儘管我認爲在每個Windows平臺上sizeof(HANDLE)'== sizeof(void *)' =='的sizeof(爲size_t)')。 –

+0

@MatteoItalia你明白爲什麼我需要這樣做,但?庫的某些部分以前會在分配上使用GlobalSize()。也許我可以用sizeof(* alloc)代替它,如果它不是void *。 –

+0

如果你預先考慮了大小,你確定使用這個內存的一切都不會弄亂它嗎?如果你的內存塊實際上是uBytes + sizeof(size_t)的話調整它? – nos

回答

2

當您分配一個塊,可以分配多一點空間,存儲你的頭在塊的開頭,然後返回一個指向一個塊(不是塊的開始)內的偏移。例如「return alloc + sizeof(MY_HEADER)」。

當你釋放一個塊時,你必須做相反的事情。例如:

BOOL BmiDibFree(HANDLE callerPointer) 
{ 
    actualPointer = callerPointer - sizeof(MY_HEADER); 
    free(actualPointer); 

注1:性能,應該確保「的sizeof(MY_HEADER)」是「的malloc()」規定的最低對齊的倍數;所以你不會給調用者造成錯位問題。注意2:您可以在塊的實際開始處和塊的實際末尾添加「canaries」(幻數),並檢查這些(在free和realloc期間)以增加檢測堆損壞的機會。我這樣做,並設置「堆已損壞」標誌,並且在任何malloc/free/realloc之前測試該標誌(如果堆被破壞,所有後續操作立即失敗以避免混亂更大)。

注3:您可以使用條件編譯(例如,「調試的#ifdef」)啓用/禁用您的包裝的各種功能。我也是這樣做的 - 一個用於啓用額外的檢查(canaries),一個用於啓用統計信息的收集/報告(分配的塊的總數,隨時分配的塊的最大數量,分配的總字節數,最大數量任何時候分配的字節數)。

0

問:你真的是指「sizeof(size_t)」?這通常只有4個字節。與「sizeof(alloc)」相同 - 可能只是「4」。

+0

sizeof(size_t)的意思是,我想分配一個額外的4個字節來存儲分配的大小。 sizeof(alloc)我甚至沒有想過,應該是alloc中的元素的數量......但是看到alloc是一個void *(HANDLE),它將是一個指針的大小? (4字節以及在我的32位操作系統上,沒有中斷,但技術上也不正確) –