Drew Noakes
Drew Noakes

Reputation: 310822

Initialise std::string in uninitialised, unowned memory

I'm using a C library (libwebsockets) which allows some user-data for each client. The library owns this memory, passes it as a void*, and my code reinterpret_cast's it to my user-data type.

I'm trying to add a std::string field to this class and am now seeing segfaults. Calling functions on this class causes errors, which is fair enough as it's likely backed by uninitialised memory.

How can I initialise that memory> I've tried assigning (the assignment operator segfaults) and calling various functions such as clear. I'm guessing there's a C++ mechanism for this.

Furthermore, how can the destructor be called when the string is no longer needed?

Upvotes: 1

Views: 173

Answers (2)

cdhowie
cdhowie

Reputation: 168988

Assuming that you have a type something like this:

class MyType
{
    std::string foo;
    std::string bar;
};

And assuming that the void * points to an uninitialized allocation of at least sizeof(MyType) bytes, then you can construct it (and all contained objects) using placement new syntax:

void init_callback(void * ptr) {
    new (ptr) MyType();
}

Similarly, you can destruct your type (which will destruct all contained objects) by calling the destructor directly.

void destroy_callback(void * ptr) {
    MyType * mine = reinterpret_cast<MyType *>(ptr);
    mine->~MyType();
}

Generally you don't call destructors directly, but you have to because you can't safely delete the pointer. The rule "every new should have one delete" has an analog in this situation: "every placement-new should have one explicit call to the destructor."

Upvotes: 2

Mike Seymour
Mike Seymour

Reputation: 254431

You can use placement-new to create an object in the provided memory:

std::string * s = new(memory) std::string;

and call the destructor to destroy it before reusing or releasing the memory:

s->std::string::~string();

If you find that a bit of a mouthful, then using std::string; will reduce it to s->~string();

Upvotes: 1

Related Questions