2011-03-08 78 views
1

我需要幫助理解下面的代碼片段... allocate是一個函數,將被重載的新運算符調用分配內存。我有問題想了解,特別是以下類型轉換:重載新的和刪除C++跟蹤內存分配

*static_cast<std::size_t*>(mem) = pAmount; //please explain? 

return static_cast<char*>(mem) + sizeof(std::size_t); //? 

和..

// get original block 
void* mem = static_cast<char*>(pMemory) - sizeof(std::size_t); //? 

的代碼如下所示:

const std::size_t allocation_limit = 1073741824; // 1G 
    std::size_t totalAllocation = 0; 

    void* allocate(std::size_t pAmount) 
    { 
     // make sure we're within bounds 
     assert(totalAllocation + pAmount < allocation_limit); 

     // over allocate to store size 
     void* mem = std::malloc(pAmount + sizeof(std::size_t)); 
     if (!mem) 
      return 0; 

     // track amount, return remainder 
     totalAllocation += pAmount; 
     *static_cast<std::size_t*>(mem) = pAmount; 

     return static_cast<char*>(mem) + sizeof(std::size_t); 
    } 

    void deallocate(void* pMemory) 
    { 
     // get original block 
     void* mem = static_cast<char*>(pMemory) - sizeof(std::size_t); 

     // track amount 
     std::size_t amount = *static_cast<std::size_t*>(mem); 
     totalAllocation -= pAmount; 

     // free 
     std::free(mem); 
    } 

回答

6

分配器保持尺寸的軌道通過將它們與它服務於客戶端代碼的塊一起保留來進行分配。當被要求輸入一個pAmount字節的數據塊時,它會在開始時分配一個額外的sizeof(size_t)字節並在那裏存儲大小。爲了達到這個尺寸,它將它從malloc得到的mem指針解釋爲size_t*,並將其解除引用(*static_cast<std::size_t*>(mem) = pAmount;)。然後它返回塊的其餘部分,該部分從mem + sizeof(size_t)開始,因爲這是客戶端可以使用的部分。

解除分配時,它必須將從malloc得到的確切指針傳遞給free。爲了得到這個指針,它將減去它在allocate成員函數中添加的sizeof(size_t)字節。

在這兩種情況下,都需要強制轉換爲char*,因爲指針算術在void指針上不被允許。

+0

所以*的static_cast <性病::爲size_t *>(MEM)= pAmount可以是寫成size_t * ptr = static_cast (mem)...這裏ptr指向分配的內存的開始,然後* ptr = pAmount; ? – maxpayne 2011-03-08 15:28:17

+0

@maxpayne:沒錯。 – 2011-03-08 15:30:36

+0

在分配函數中,返回0和返回NULL是否有區別?僅僅是一個值爲0的宏? – maxpayne 2011-03-08 15:36:22

0

爲了知道在刪除內存時需要清理多少內存(並提供一些診斷),分配器會將這個大小存儲在額外分配的內存中。

* static_cast(mem)= pAmount; //請解釋?

這需要分配的內存並將分配的字節數存儲到此位置。出於存儲目的,演員將原始存儲器視爲size_t

return static_cast(mem)+ sizeof(std :: size_t); //?

這將向前移動超過字節大小到您的應用程序將使用的實際內存並返回該指針。

無效* MEM = 的static_cast(pMemory) - 的sizeof(標準::爲size_t); //?

這是將先前返回給用戶的塊並前進回存儲較大尺寸的「實際」分配塊。需要檢查並回收內存。

+0

取消分配時不需要額外的信息。 '免費'處理。 – 2011-03-08 15:01:04

0

爲了獲得正確的偏移量,需要強制轉換,因爲void *不是具有大小的類型。

當你寫

回報的static_cast(MEM)+的sizeof(標準::爲size_t);

在添加偏移量字節之前,將指針轉換爲char *。

同樣在分配時減去。

2

void *的分配(標準::爲size_t pAmount)

分配的內存空間,加上對pAmount存儲大小

|-size-|---- pAmount of memory-----| 

^
    | 

「分配」 將返回一個指針剛剛粘貼的大小字段。

void deallocate(void* pMemory) 

將指針移動回到開始

|-size-|---- pAmount of memory-----| 

^ 
| 

和自由吧。

1)

std::size_t mySize = 0; 

void * men = & mySize; 

// same as: mySize = 42; 
*static_cast<std::size_t*>(mem) = 42; 

std::cout << mySize; 
// prints "42" 

2.)

`return static_cast<char*>(mem) + sizeof(std::size_t); 
// casts void pointer mem to a char* so that you can do pointer arithmetic. 
// same as 

char *myPointer = (char*)mem; 

// increment myPointer by the size of size_t 
return myPointer + sizeof(std::size_t); 

3.)

`void* mem = static_cast<char*>(pMemory) - sizeof(std::size_t);` 
// mem points size of size_t before pMemory 
+0

+1感謝您的簡單例子... – maxpayne 2011-03-08 15:29:30