Pedro Toledo Correa
Pedro Toledo Correa

Reputation: 35

Array of strings with malloc on C++

For a list of reasons that I do not control, I need to create an array of strings that needs to be referenced from a void* pointer. The idea is to follow the following pattern in C++:

void* TP = malloc(sizeof (double) * SS);
for (int i = 0; i < SS; i++) {
  ((double*) TP)[i] = IStringToDouble(Token[i]);
}

Where Token is a vector and SS an int. Now, using that template, I though starting with something like:

void* TP = malloc(sizeof (string) * SS);
for (int i = 0; i < SS; i++) {
  ((string*) TP)[i] = Token[i];
}

I know that this is horribly wrong, but all the modifications I have tried starting from it don't work.

Any suggestion about how to achieve this? Is it possible?

I have gone through all the documentation about string arrays on C++ that I have found from Google or StackOverflow, but none of them covers the issue about referencing the array from a void*.

Upvotes: 0

Views: 3622

Answers (2)

Tony Delroy
Tony Delroy

Reputation: 106244

void* TP = malloc(sizeof (string) * SS);
for (int i = 0; i < SS; i++) {
  ((string*) TP)[i] = Token[i];
}

This is horrible, but I'll ignore that and explain why it's broken and how to get it working....

malloc() allocates memory but doesn't construct any objects in it. For string, you need to invoke the constructor - otherwise the new string instances will contain uninitialised pointer members that the string object will assume are pointers to memory for the actual text data: ((string*) TP)[i] = Token[i]; will then try to ensure capacity and overwrite memory based on these garbage values.

To fix this, use the placement-new operator to construct each of the strings:

void* TP = malloc(sizeof (string) * SS);
for (int i = 0; i < SS; i++) {
  new (&((string*)TP)[i]) std::string(Token[i]);
}

You'll need to destroy the strings similarly afterwards by calling their destructors explicitly, and then free() the array.

Upvotes: 1

You can convert any pointer to a void* already. You do not need to use malloc, and you do not need to have the void* pointer as the only pointer to the object.

With that in mind, why not do this?

string* TP = new string[SS];
for (int i = 0; i < SS; i++) {
    TP[i] = Token[i];
}

void *TP2 = TP;

or even this:

void *TP = &Token[0];

although, with the second method, the pointer will be invalidated if you add more elements to Token, and modifying the strings through this pointer will modify the strings in Token (since that's what the pointer's pointing to).

Upvotes: 4

Related Questions