简体   繁体   中英

Deleting an array of std::string allocated with malloc in C++

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?

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM