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

これらの値が異なる理由がよくわかりません。私が理解しているように、配置 new は、アドレス 'BufferPtr' で始まるメモリを使用して、割り当てられたメモリのデフォルト コンストラクタを使用して配列要素を初期化し、配列内の最初の要素の最初のバイトへのポインタを返す必要があります。プレースメント 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、これは実際には素晴らしい質問です。プレースメント new[] を使用したとき、ストレージの削除に問題がありました。独自の対称配置の delete[] を呼び出しても、ポインタ アドレスは、独自の配置 new[] によって返されたものと同じではありません。コメントで提案したように、これにより配置 new[] は完全に役に立たなくなります。

私が見つけた唯一の解決策は、Jonathan @ によって提案されました。配置 new[] の代わりに、配列の各要素に配置 new (非配列) を使用します。自分でサイズを保管しているので、これで問題ありません。問題は、要素のポインターの配置について心配する必要があることです。これは、 new[] が私のために行うはずです。

于 2013-06-18T21:40:11.410 に答える