Variable size class - C ++

I've seen a class that is a class that is defined like this.

class StringChild : public StringBase
    {
public:
    //some non-virtual functions
    static StringChild* CreateMe(int size);
private:
    unsigned char iBuf[1];
    };

      

The static factory function has the following implementation.

return new(malloc(__builtin_offsetof(StringChild ,iBuf[size]))) StringChild();

      

So, as far as I understand, this function uses the placement new to extend this class.

Is it safe just because there is only one member and it is allocated on the heap?

+1


source to share


3 answers


This is an old C trick that was used to get around the invalidation of variable length arrays in plain C. Yes, it also works in C ++ as long as you use appropriate allocator constructs (for example, allocating a heap of raw memory the size you want, then allocating a new object there). This is safe as long as you don't wander around the end of the allocated memory, but it tends to confuse at least some memory debuggers.

One thing you must make absolutely sure when using this method is that the variable length array is the last element in the object's layout, otherwise you will pass other internal variables.



However, I am a little doubtful about the implementation of the factory function - I am assuming that the "size" parameter is actually the desired size of the array? Also, don't forget that you will have to free the memory above using "free" and not "delete", although the latter might work in most cases.

Unless there is a compelling reason why memory should be managed in this way, I would simply replace the std :: vector array.

+5


source


This should be OK for the POD if the iBuf is the last member of the structure. Problems with non-PODs can be like this. the compiler is free to reorder public / private / protected members, virtual base classes end at the end of the most derived IIUC object, etc.

Your structure is non-POD (has a base class), so I would not recommend it.

Also, if you create instances like this

return new(malloc(__builtin_offsetof(StringChild ,iBuf[size]))) StringChild();

      



You have to make sure that the memory received by malloc should be freed for free, so remove your instances like this:

obj->~StringChild();
free(obj);

      

You might want to use ::operator new()

for posting

+3


source


Strictly speaking, since it is StringChild

obtained from StringBase

, it is not safe. The C ++ standard does not specify a layout for base class subobjects. Clause 10 Clause 3:

The order in which base class subobjects are allocated in the most derived object (1.8) is not specified.

If there StringChild

was a POD structure, then such a technique would be safe.

0


source







All Articles