0

This is a follow up from my question at: Array of strings with malloc on C++

As I have implemented Tony D solution, I have allocated memory for an array of std::string with malloc and then created the std:string for each one of the elements with new according to:

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

(Token is a vector<string> and SS an int)

I know this is not recommended, I know it is not elegant, I know there are many other solutions for this array creation and filling, but I need to do it this way

The issue I encounter now is at the array deletion. As I create each std::string separately but the allocation for the array with a malloc, in my destructor I have written:

for (int i = 0; i < SS; i++) {
  delete (&((string*) TP)[i]);
}
free(TP);

But when running, the free(TP) is accusing a "double free or corruption".

By commenting the free(TP) I solve the issue for runtime (hidding the real issue), but I need to be sure all memory is released as this may cause a memory leak within the class.

So, is the deletion of each element of TP enough to free all that memory? From my understanding the malloc has allocated memory independently and it needs to be free independently from the std::string elements; but then, why do I get this error?

2
  • 2
    Don't use any new or malloc or similar things directly. Use RAII facilities! Commented Jan 21, 2015 at 1:14
  • 1
    "By commenting the free(TP) I solve the issue"... No, that hides the issue. That does not solve the issue. Commented Jan 21, 2015 at 1:21

2 Answers 2

6

You're doing a placement-new to run std::string's constructor on the malloc allocated block, but then you're using delete which will run the destructor AND try to free the memory (you don't want to do the second one here since you're freeing with free()).

You want to run the destructor manually, like this...

for (int i = 0; i < SS; i++) {
  (&((string*) TP)[i])->~string();
}
free(TP);
Sign up to request clarification or add additional context in comments.

3 Comments

In other words, the matching operation for "placement new" is "call the destructor."
string* sp = (string*)TP; for (int i = 0; i < SS; i++) (sp+i)->~string(); Much simpler.
Hi Nick, It worked perfectly. I had the impression that something as you showed up was happening when deleting the first element of the array, but I am not very familiar with the constructor/destructor of this std:: classes.
1

First, let's clean up your code. I suggest you stay away from void* for your array type. Then you can do this, which is a little easier to read, especially on the new() operator:

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

Now, to free the strings, you have to call their destructor directly, don't use delete (there is no placement-delete operator, like you are assuming):

for (int i = 0; i < SS; i++) {
  TP[i].~string();
}
free(TP);

Now, with that said, you clearly have access to std::vector, so there is no good reason to use malloc() instead:

std::vector<std::string> TP(SS);
for (int i = 0; i < SS; i++) {
  TP[i] = Token[i];
}

Or:

std::vector<std::string> TP;
TP.reserve(SS);
for (int i = 0; i < SS; i++) {
  TP.push_back(Token[i]);
}

Or:

std::vector<std::string> TP(Token.begin(), Token.begin()+SS);

Comments

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.