
I've a situation like the following, and I'm not sure whether or not the std::string elements of the struct leak memory or if this is ok. Is the memory allocated by those two std::strings deleted when free(v)
is called?
struct MyData
{
std::string s1;
std::string s2;
};
void* v = malloc(sizeof(MyData));
...
MyData* d = static_cast<MyData*>(v);
d->s1 = "asdf";
d->s2 = "1234";
...
free(v);
Leak or not?
I'm using the void-pointer because I have another superior struct, which consists of an enum and a void-pointer. Depending on the value of the enum-variable, the void* will point to different data-structs.
Example:
enum-field has EnumValue01 => void-pointer will point to a malloc'd MyData01 struct
enum-field has EnumValue02 => void-pointer will point to a malloc'd MyData02 struct
Suggestions for different approaches are very appreciated, of course.
Answer1:
There is a leak indeed. free doesn't call MyData destructor (after all it's a C function which doesn't know anything about C++ stuff). Either you should use new/delete instead of malloc/free:
MyData* d = new MyData; d->s1 = "asdf"; d->s2 = "1234"; delete d;
</pre>or call destructor by yourself:
void* v = malloc(sizeof(MyData)); MyData* d = new (v) MyData; // use placement new instead of static_cast d->s1 = "asdf"; d->s2 = "1234"; ... d->~MyData(); free(v);
</pre>as sharptooth noted you can't directly use memory allocated by malloc as a MyData struct without initialization, so you have to do it by yourself as well. To initialize MyData using already allocated memory you need to use placement new (see in the code above).
Answer2:
You shouldn't be using
malloc()
andfree()
in a C++ program; they're not constructor/destructor-aware.Use the
new
anddelete
operators.Answer3:
That's undefined behavior - memory allocated by
malloc()
in uninitialized, so using it as a struct containingstring
objects can lead to anything; I'd expect crashing. Since no-one invokes the destructor before callingfree()
,string
objects won't be destroyed and their buffers will almost definitely leak.Answer4:
Yes, because the constructor and destructor are not called. Use
new
anddelete
.Answer5:
Even if you manage to initialize s1 and s2 properly, simply doing free(d) won't reclaim any memory dynamically allocated for s1 and s2. You should really create *d through new and destroy through delete, which will ensure proper destruction of s1 and s2 (and initialization as well).
Answer6:
Yes, you are probably leaking, and your strings aren't properly constructed, either. The program's behaviour is undefined, meaning everything is going to go wrong.
The closest valid way to do what you're doing is placement
new
. Still, you'd be better off with some common base class and proper C++ polymorphism.If the possible types are unrelated, you can use Boost.Any or Boost.Variant.