2010-11-01 50 views
3

有没有办法获得堆上先前分配内存的大小?
例如:了解堆上预留内存的大小

//pseudo-code 

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

您的意思是,以前在函数的代码中,线程的控制流还是由您的进程在堆上分配? – einpoklum 2013-08-06 11:58:57

回答

8

你不能在任何时候都做到这一点,因为operator new()可以在任何合理的方式过载,甚至不使用运行时堆。

如果在Visual C++中使用malloc()实现operator new(),则可以使用_msize()

5

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

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

delete运算符应该做相反:从指针

  • 减8字节的应用程序
  • 调用系统的内存取消分配常规

如果你做这种方式给出,确保实现所有类型的新和删除(投掷和不投掷,新和新[],删除和删除[],...)。

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

编辑:

舍入到8个字节的倍数和相加的8个字节是必要的,因为数据应储存在一个ADDRES这是它的大小的倍数:

  • 字符可以再存储
  • 短裤必须存储在偶数地址
  • 多头必须存储在这4
  • 一个倍数的地址0
  • 双打必须存储在这8

由于双打,我所知道的最大的原生数据类型,我们四舍五入为8个字节的倍数倍数的地址,我们增加8个字节,使确保保持这些要求。

+1

为什么只有8个字节,而不是“足够的字节来存储'size_t'变量”? – sharptooth 2010-11-01 10:32:57

+0

由于本地数据类型需要存储在大小为其倍数的地址上。通常,最大的数据类型是双倍的,即8个字节。因此,我们需要添加8个字节的大小和指针,以保持8个字节的倍数。 (为我的帖子添加一个小小的更正,以确保我们保留8个字节的倍数)。 – Patrick 2010-11-01 11:18:30

+0

好的,我明白了。那么不应该是'max(sizeof(double),sizeof(void *))'或类似的东西,以便代码可以移植到1024(或其他)位计算机? – sharptooth 2010-11-01 11:52:46

1
  • 您可以重写new操作者调用malloc()和大小存储在一个全局std::map<void*, size> alloc

那么这​​功能会像你想:

getSomeHow(void *p){ 
    return alloc[p]; 
} 
  • 您也可以编写自己的malloc(),并设置加载器使用的malloc而不是标准之一。我已经完成了追踪目的,它工作正常。
+0

这很好,但为什么不只是分配一个更大的块,在开始时写入分配的大小并返回一个偏移量指针? – sharptooth 2010-11-01 10:31:49

+0

嗯,是的,它实际上好多了! – Ben 2010-11-01 10:39:49

+0

@Ben你会提供一些提示如何写我自己的malloc?它非常感兴趣。在此先感谢 – 2010-11-01 10:53:47