安置新 +数组对齐

发布于 2024-09-29 09:40:54 字数 2978 浏览 3 评论 0原文

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

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

我是否理解错误,或者有人可以告诉我为什么价值观不同?

谢谢!

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

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

};

任何人都可以解释一下我这是怎么了?谢谢!

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

when I step past these lines with the debugger, it shows me the values for the variables Buffer and BufferPtr:

BufferPtr: 0x0d7f004c
Buffer:    0x0d7f0050

I don't really understand why those values differ. The way I understand it, placement new should use the memory starting at address 'BufferPtr' to initialize the array elements using theyr default constructors on the allocated memory and return a pointer to the first byte of the first element in the array, which should be exactly the same byte as passed to the placement new operator.

Did I understand something wrong or can someone tell me why the values differ?

thanks!

//edit: ok - i investigated the issue further and got more confusing results:

    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];

the debugger returns me the following values for my variables:

size: 4

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

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

so it clearly must have something to do with my generic smartpointer class matth_ptr so here it is:

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

};

can anyone explain me what's going on? thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

风吹过旳痕迹 2024-10-06 09:40:55

在数组上放置 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,其中表示放置 new 运算符仅返回提供的指针。这显然是预期的部分。

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

Be careful with placement new on arrays. In the current standard look to section 5.3.4.12, you'll find this:

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

It is clear that it will expect the placement new operator to allocate it additional space beyond what the array contents need. "y" is specified only as a non-negative integral value. It will then offset the result of the new function by this amount.

Also look to 18.4.1.3.4 where it says the placement new operator simply returns the provided pointer. This is obviously the expected part.

Based on 5.3.4.12, since that offset may be different for every invocation of the array, the standard basically means there is no way to allocate the exact amount of size needed. In practice that value is probably constant and you could just add it to the allocation, but his amount may change per platform, and again, per invocation as the standard says.

隔岸观火 2024-10-06 09:40:55

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

You're using the array version of the new operator which in your implementation is storing information about the array size in the first few bytes of the memory allocation.

黑寡妇 2024-10-06 09:40:55

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

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

@Mat, This is actually a great question. When I've used placement new[], I've had trouble deleting the storage. Even if I call my own symmetrical placement delete[], the pointer address is not the same as was returned by my own placement new[]. This makes placement new[] completely useless, as you've suggested in the comments.

The only solution I've found was suggested by Jonathan@: Instead of placement new[], use placement new (non-array) on each of the elements of the array. This is fine for me as I store the size myself. The problem is that I have to worry about pointer alignments for elements, which new[] is supposed to do for me.

冰雪之触 2024-10-06 09:40:55

正如其他人所说,这是由于您的 C++ 实现将数组的大小存储在您传递给数组放置新的缓冲区的开头。

解决这个问题的一个简单方法是简单地将数组指针分配给缓冲区,然后循环数组并使用常规(非数组)放置 new 来构造缓冲区中的每个对象。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文