了解堆上保留内存的大小

时间:2010-11-01 10:19:19

标签: c++

有没有办法在堆上获取以前分配的内存的大小? 例如:

//pseudo-code

void* p = operator new (sizeof(int) * 3);
unsigned size = getSomeHow(p);  

3 个答案:

答案 0 :(得分:8)

你无法一直这样做,因为operator new()可以以任何合理的方式重载,甚至可以不使用运行时堆。

如果在{C}中使用operator new()实现malloc(),您可以使用_msize()

答案 1 :(得分:5)

虽然Sharptooth在他的回答中是正确的(新的可以超载),但解决方案可能只是在这个事实。通过重载新的,您可以轻松添加自己的新实现和删除。在您的新实施中,您应该:

  • 编辑:将大小调整为下一个8字节的倍数
  • 将8个字节添加到应用程序请求的大小
  • 调用系统内存分配例程(例如Windows中的HeapAlloc)
  • 在前8个字节中填写原始请求的大小
  • 将8添加到返回的指针并将其返回给应用程序

删除操作符应该相反:

  • 从应用程序给出的指针中减去8个字节
  • 调用系统内存释放例程

如果你这样做,请确保实现所有新的和删除(抛出和非抛出,新的和新的[],删除和删除[],...)。

另外要小心第三方库。他们有时会在他们的DLL编译代码中调用new,但是在头文件中调用delete。这意味着new和delete将使用不同的实现,您的应用程序将崩溃。

修改

需要舍入到8个字节的倍数并添加8个字节,因为数据应存储在其大小的倍数的地址中:

  • 字符可以再存储
  • 短裤必须存储在偶数地址
  • longs必须存储在4的倍数的地址
  • 双打必须存储在8的倍数的地址

由于双精度是我所知道的最大的本机数据类型,我们将其舍入为8个字节的倍数,并添加8个字节以确保保持这些要求。

答案 2 :(得分:1)

  • 您可以重写new运算符以调用malloc()并将大小存储在全局std::map<void*, size> alloc中。

然后这个getSomeHow()函数的行为就像你想要的那样:

getSomeHow(void *p){
  return alloc[p]; 
}
  • 您也可以编写自己的malloc()并将加载程序设置为使用malloc而不是标准的malloc。我这样做是为了追踪目的,它运作正常。