重载新的和删除C ++以跟踪内存分配

时间:2011-03-08 14:41:44

标签: c++ memory operator-overloading allocation new-operator

我需要帮助理解下面剪切的代码... allocate是一个由重载的new运算符调用来分配内存的函数。我在尝试理解以下演员表时遇到了问题:

*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);
    }

4 个答案:

答案 0 :(得分:6)

分配器通过将分配与它为客户端代码提供的块一起保存来跟踪分配的大小。当被要求输入pAmount个字节时,它会在开头分配一个额外的sizeof(size_t)个字节,并在那里存储大小。要达到此大小,它会将mem指针从malloc解释为size_t*并解除引用(*static_cast<std::size_t*>(mem) = pAmount;)。然后它返回块的其余部分,从mem + sizeof(size_t)开始,因为这是客户端可能使用的部分。

取消分配时,必须将从malloc获取的确切指针传递给free。要获取此指针,它会减去sizeof(size_t)成员函数中添加的allocate个字节。

在这两种情况下,都需要转换为char*,因为void指针上不允许使用指针运算。

答案 1 :(得分:2)

void * allocate(std :: size_t pAmount)

分配pAmount内存加空间来存储大小

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

   ^
   |

“allocate”将返回一个仅粘贴size字段的指针。

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

答案 2 :(得分:0)

为了知道在删除它时要清理多少内存(并提供一些诊断),分配器会在额外分配的内存中存储大小。

  

* static_cast(mem)= pAmount; //请解释一下?

这将获取已分配的内存并将分配的字节数存储到此位置。为了存储目的,强制转换将原始内存视为size_t

  

返回static_cast(mem)+   的sizeof(标准::为size_t); //?

这会将大小字节向前移动到应用程序将使用的实际内存并返回该指针。

  

void * mem =   static_cast(pMemory) -   的sizeof(标准::为size_t); //?

这是先前返回给用户的块,然后返回到先前存储大小的“真实”分配块。需要做检查并回收内存。

答案 3 :(得分:0)

需要使用强制转换以获得正确的偏移,因为void *不是具有大小的类型。

当你写

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

在添加偏移字节之前,指针被强制转换为char *。

在解除分配时减去ditto。