0

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*.

10
  • 2
    Don't use malloc in C++. Especially not with std::string. Commented Jan 20, 2015 at 2:20
  • Hi Borgleader, I know that, any suggestion to fulfill the request for the void* pointer, with or without malloc, would be very useful. Commented Jan 20, 2015 at 2:22
  • What is Token[i], and how will the strings be accessed? Commented Jan 20, 2015 at 2:30
  • Hi Matt, Token is a vector<string>, so Token[i] returns a string already initialized. The strings will be used by other functions that only accept void* as parameter, but those functions have all the information required to reference the position and cast the pointer. Commented Jan 20, 2015 at 2:32
  • Could you make TP's pointers just point into that vector then? Instead of trying to allocate new strings? Commented Jan 20, 2015 at 2:33

2 Answers 2

4

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).

Sign up to request clarification or add additional context in comments.

2 Comments

Hi immibis, thank you very much, it worked exactly how I wanted. I had tried a very similar solution prior to posting the question, but the use of a different variable to cast the TP array made the difference.
a std::vector<std::string> would be much better than new string[]. You can use &TP[0] or TP.data() to get a pointer to the first element of a vector.
1
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.

5 Comments

Hi Tony, you pointed out exactly what I knew was wrong about the uninitialized strings from the memory allocation. Could you please check the "new" line? It seems that there is a parenthesis issue.
Thank you very much, it worked perfectly and very similar to the original template I had in mind.
&((string*)TP)[i] simplifies to i + (string*)TP, btw.
"You'll need to delete the strings similarly afterwards." - no, that would be undefined behavior. You allocated with malloc(), so must free(). But yes, you must first "destroy" (not delete) the strings, which you can do by explicitly calling their destructors in a loop. This led directly to another question here: stackoverflow.com/questions/28057999/…
@JohnZwinck: yes - careless of me. Thanks for correcting this answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.