7

How should a c++ class be used when its memory has been reserved from a C malloc?

I'm using a C library (lua) and I need to expose a C++ class to it, in this case in order to garbage collect these reserved space, lua does the memory reservation.

A simpler similar scenario follows:

#include <string>

class Clase{
private:
    std::string valor;
public:
    Clase(){}
    Clase(const std::string & valor) : valor(valor){}
    const std::string & get() const { return this->valor; }
    void set(const std::string & valor){ this->valor = valor;}
    ~Clase(){}
};

typedef struct
{
    Clase cls;
}Estructura;

int main(int argc, char ** argv)
{
    Estructura * est = (Estructura *) malloc(sizeof(Estructura));

    est->cls.set("Hola");   // First attempt

    Clase myCls;   // Second attempt
    est->cls = myCls;

    return 0;
}

I understand, and have checked, that with malloc the class constructor is not called; that was expected, and so the copy (assign) operator can't be called with an invalid instance (the string inside Class). I suspect that the second attempt fails in the same point, when copying the string inside the Class instance.

So:

  • is it possible to correctly initialize a class instance that had its memory reserved by malloc?
  • what other caveats are there?, vtables?
  • would the free complementary to the malloc leave memory leaks? (I'm guessing that since the Clase destructor won't be called the string won't be correctly freed? [I'm assuming that string holds memory outside the instance itself])

Using pointer for the Clase inside Estructura, works well, is this the best solution?

And as bonus, best way to delete the instance when lua garbage collects it?, using the __gc metamethod or is something better?

PJTraill
  • 1,353
  • 12
  • 30
Javier Mr
  • 2,130
  • 4
  • 31
  • 39
  • 2
    http://stackoverflow.com/a/222578/3385212 – tynn May 05 '15 at 07:49
  • The best solution could be to write a mid level wrapper to interface C to C++. Start defining a C++ function, outsid a class, that use new to init the class and return the pointer of the created object. The create wrapper for public methods. – LPs May 05 '15 at 07:50
  • Why do you have the `Estructura` wrapper? (And there is no pointer in your code, btw.) – Peter - Reinstate Monica May 05 '15 at 08:05
  • (I mean, no ponter inside `Estructura`.) – Peter - Reinstate Monica May 05 '15 at 08:10
  • Yea, initially I was hopping to have the Clase instance inside the struct, not a pointer so when the struct gets deleted (or its memory freed) the instance would also get delete. That wrapper is there because is may have more fields in the future. – Javier Mr May 05 '15 at 08:40

1 Answers1

14

It's a bit odd to use malloc instead of new, but it is possible. You need to use placement new:

void *memory = malloc(sizeof(Estructura));

Estructura *est = new(memory)Estructura;

When you're finished with the object it's your responsibility to call the destructor yourself:

est->~Estructura();

Everything, such as vtables, will be correctly initialized, so there's no need to worry. The awkward bit is dealing with the deletion as you need to destruct the object before releasing the memory via free. delete does this automatically for you, but you'll need to do this yourself.

Sean
  • 60,939
  • 11
  • 97
  • 136