2017-05-16 24 views
0

不确定“标题”是否是正确的术语,所以如果不是,请更正。我想先分配一个内存,然后使用重载(放置)new []运算符来初始化一个类对象(比如MyClass)的数组。用于WDK的C++中数组的标题大小

说,一个MyClass对象的大小是0x68,我想要一个0x20的数组。所以总大小是sizeof(MyClass)* 0x20 = 0xD00,或者我想。

现在,当我用我的重载放置新的[]操作:

pArr = new(pAllocatedMem)MyClass[0x20]; 

编译器返回的size_t新的[]运营商实际上是量0xD08。还有一个额外的8字节。看看这8个字节的值,它用来存储数组的大小(在这种情况下是0x20)。

那么是否有一个这种头部大小的恒定定义,比如来自WDK的我可以使用?这个大小的变化取决于编译器还是其他什么?

回答

2

该额外空间的量(如果有)与编译器相关。对于languange定义[expr.new,paragraph 15]:

[It]是表示数组分配开销的非负数未指定值;新表达式的结果将被运算符new []返回的值所抵消。

它通常用于运行时知道在阵列上最终调用delete时要销毁多少个对象。

+0

你知道VC的开销是否经常被定义? – Andrew

+0

@Andrew:你有来源。但我不认为这是官方的;它可能会在不同版本之间变化毕竟,便携式代码无论如何都不能依赖它,所以为什么VC会从记录中受益? – MSalters

+0

@MSalters,**是否保证开销相同,至少在运行我的程序(驱动程序)的同一实例内?**看来我无法安全地使用新的[]安置。释放分配的内存将导致BSOD(我在Windows上),如果未指定的开销没有被正确解释。我需要在删除期间传递一个参数,但删除[]不能接受额外的参数,并且de /在new/delete之外分配内存将会产生这种开销。 – Andrew

0

自己添加到答案中。 与同事做了一点测试。如果要初始化的类具有已定义的析构函数,则VS编译器将需要用于存储数组大小的开销。没有析构函数,没有开销。这是一个错误还是一个特性?!

#include <malloc.h> 
#include <new> 

class Foo 
{ 
public: 
    //Foo() {} 
    //~Foo() {} // <-- will cause overhead even with user-allocated memory passed to placement new() 
    int a; 
}; 

int main() 
{ 
    int n = 0x10; 
    size_t size = sizeof(int) * 2 + sizeof(Foo) * n; 
    void* p = malloc(size); 
    *((int*)p) = 0xaaaaaaaa; 
    *(int*)((char*)p + size - sizeof(int)) = 0xbbbbbbbb; 
    // Placement new with user-allocated memory 
    Foo* pf = new ((char*)p + sizeof(int)) Foo[n]; 
    for (int i = 0; i < n; i++) 
    { 
     pf[i].a = i; 
    } 
    free(p); 
    return 0; 
}