Sunday, November 3, 2013

Tech talks: placement new

So another post under sign of programming. This time: placement new. So lets's look on this part of code :
   
...

if (techData.texturesCount[idx] > 0)

{
    tech->m_textures = new(memoryPtr) STextureSlot[tech->m_texturesCapacity];
    memoryPtr += sizeof(STextureSlot) * tech->m_texturesCapacity;
}
else
{
    tech->m_textures = NULL;
}

...


It's a part of White Rabbit Engine materials creator. It's purpose is simple : allocate memory for material + techniques + textures slots. And use placement new to create objects. Everything so all materials data was put in continuous memory. Of course it's nice but there is one problem : this part of code is wrong.

Everything look nice but placement new for arrays add additional data about array before objects. So

  new(memoryPtr) STextureSlot[tech->m_texturesCapacity]

use more memory than :

  sizeof(STextureSlot) * tech->m_texturesCapacity;

For me this mistake ended long looking for place where I override memory and knowledge about two things:
  • placement new for arrays add this additional data. 
  • it's really nice to have memory guards. But it's even nicer when you check on deleting if it wasn't override :]

Till next post.

2 comments:

  1. Hey!
    How did you handle it eventually?

    ReplyDelete
  2. Hi :]

    In this case solution was straight forward: Initialize objects separately inside the loop. I solved problem this way because this code is one of the preparations for final form of material serialization. So I wanted data there to be packed really tightly. Also from what I checked the amount of memory may vary on different compilers so I would need to do some tricks to read this data later.

    Of course there is solution for people that want use placement new for arrays anyway. It is to first check how big this additional memory is. You can do that i.e :

    char* memoryPtr = ....
    MyStruct* a = new(memoryPtr) MyStruct[0];
    ptrdiff_t sizeOfAdditionalMemory = ((char*)a) - memoryPtr;

    ReplyDelete