12
SomeObj<unsigned int>* Buffer;
char* BufferPtr = MemoryManager::giveMeSomeBytes(resX*resY*sizeof(SomeObj<unsigned int>));
Buffer = new(BufferPtr) SomeObj<unsigned int>[resX*resY];

当我使用调试器跳过这些行时,它会显示变量 Buffer 和 BufferPtr 的值:

BufferPtr: 0x0d7f004c
Buffer:    0x0d7f0050

我真的不明白为什么这些价值观不同。按照我的理解,placement new 应该使用从地址“BufferPtr”开始的内存来使用分配内存上的默认构造函数初始化数组元素,并返回指向数组中第一个元素的第一个字节的指针,这应该是与传递给placement new 操作符的字节完全相同。

我是否理解错误或有人可以告诉我为什么这些值不同?

谢谢!

//编辑:好的 - 我进一步调查了这个问题并得到了更令人困惑的结果:

    int size = sizeof(matth_ptr<int>);

    char* testPtr1 = (char*)malloc(a_resX*a_resY*sizeof(int));
    int* test1 = new(testPtr1) int[a_resX*a_resY];

    char* testPtr2 = mmgr::requestMemory(a_resX*a_resY*sizeof(int));
    int* test2 = new(testPtr2) int[a_resX*a_resY];

    char* testPtr3 = (char*)malloc(a_resX*a_resY*sizeof(matth_ptr<int>));
    matth_ptr<int>* test3 = new(testPtr3)matth_ptr<int>[a_resX*a_resY];

    char* testPtr4 = mmgr::requestMemory(a_resX*a_resY*sizeof(matth_ptr<int>));
    matth_ptr<int>* test4 = new(testPtr4)matth_ptr<int>[a_resX*a_resY];

调试器为我的变量返回以下值:

size: 4

testPtr1:0x05100418
test1:   0x05100418
testPtr2:0x0da80050
test2:   0x0da80050

testPtr3:0x05101458
test3:   0x0510145c
testPtr4:0x0da81050
test4:   0x0da81054

所以它显然必须与我的通用智能指针类 matth_ptr 有关,所以它是:

template <class X> class matth_ptr
{
public:
    typedef X element_type;

    matth_ptr(){
        memoryOfst = 0xFFFFFFFF;
    } 

    matth_ptr(X* p) 
    {
        unsigned char idx = mmgr::getCurrentChunkIdx();
        memoryOfst = (int)p-(int)mmgr::getBaseAddress(idx);
        assert(memoryOfst<=0x00FFFFFF || p==0);//NULL pointer is not yet handled
        chunkIdx = idx;
    }
    ~matth_ptr()                {}
    X& operator*()              {return *((X*)(mmgr::getBaseAddress(chunkIdx)+(memoryOfst&0x00FFFFFF)));}
    X* operator->()             {return  ((X*)(mmgr::getBaseAddress(chunkIdx)+(memoryOfst&0x00FFFFFF)));}
    X* get()                    {return  ((X*)(mmgr::getBaseAddress(chunkIdx)+(memoryOfst&0x00FFFFFF)));}


    template<typename T>
    matth_ptr(const matth_ptr<T>& other) {memoryOfst=other.memoryOfst;}//put these two operators into the private part in order to prevent copying of the smartpointers
    template<typename T>
    matth_ptr& operator=(const matth_ptr<T>& other) {memoryOfst = other.memoryOfst; return *this;}
    template<typename T>
    friend class matth_ptr;
private:

    union //4GB adressable in chunks of 16 MB
    {
        struct{
            unsigned char padding[3]; //3 bytes padding
            unsigned char chunkIdx; //8 bit chunk index
        };
        unsigned int memoryOfst; //24bit address ofst
    };

};

谁能解释我发生了什么事?谢谢!

4

4 回答 4

14

在阵列上放置 new 时要小心。在当前的标准中查看第 5.3.4.12 节,您会发现:

new(2,f) T[5] results in a call of operator new[](sizeof(T)*5+y,2,f)

很明显,它将期望放置 new 运算符为其分配超出数组内容所需的额外空间。“y”仅指定为非负整数值。然后它将以这个量抵消新函数的结果。

还要查看 18.4.1.3.4 ,它说placement new 运算符只返回提供的指针。这显然是预期的部分。

基于 5.3.4.12,由于每次调用数组的偏移量可能不同,因此该标准基本上意味着无法分配所需的确切大小。在实践中,该值可能是恒定的,您可以将其添加到分配中,但他的数量可能会在每个平台上发生变化,并且再次按照标准所说的每次调用发生变化。

于 2010-10-25T07:13:58.150 回答
6

您正在使用new运算符的数组版本,它在您的实现中将有关数组大小的信息存储在内存分配的前几个字节中。

于 2010-10-25T04:21:46.437 回答
2

@Mat,这实际上是一个很好的问题。当我使用placement new[] 时,我在删除存储时遇到了麻烦。即使我调用我自己的对称放置delete[],指针地址也与我自己的放置new[]返回的一样。正如您在评论中所建议的那样,这使得放置 new[] 完全没用。

我发现的唯一解决方案是 Jonathan@ 建议的:在数组的每个元素上使用placement new(非数组)而不是placement new[]。这对我来说很好,因为我自己存储尺寸。问题是我必须担心元素的指针对齐,new[] 应该为我做。

于 2013-06-18T21:40:11.410 回答
1

As others have said, this is due to your C++ implementation storing the size of the array at the start of the buffer you pass to array placement new.

An easy fix for this is to simply assign your array pointer to the buffer, then loop over the array and use regular (non-array) placement new to construct each object in the buffer.

于 2013-04-19T05:33:13.850 回答