Chris
Chris

Reputation: 31256

C++: free or destroy malloc'd char * after it is captured by a local string?

Suppose I do the following:

char *get_data(...) {
    char *c_style = (char *) malloc(length * sizeof(char));
    load_c_string_with_my_c_function(c_style, length, input);
    return c_style;
}

int main() {
   std::string data(get_data(...));
   // free(data.c_str()); ?? -- are the malloc'd bytes now managed?
   return 0;
}

Is there any way to release the memory that get_data() allocated? Would the commented free(data.c_str()); Work?

Upvotes: 1

Views: 504

Answers (4)

Blaze
Blaze

Reputation: 16876

You can't call call free(data.c_str()); or anything like that. std::string manages its own memory and even the pointer that you get from c_str() is invalidated automatically as soon as the std::string goes out of scope.

You do, however, need to free the c_style returned from the function call. The std::string may handle its own memory, but it is only a copy of the malloc'd memory that isn't managed.

Do this:

int main() {
    char *result = (get_data(...)
    std::string data(result);
    // free(data.c_str()); ?? -- are the malloc'd bytes now managed?
    free(result);
    return 0;
}

Upvotes: 2

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385264

Is there any way to release the memory that get_data() allocated?

No, you lost your pointer to it.

Would the commented free(data.c_str()); Work?

No. The std::string copied your data into a new string that it owns and manages. You cannot legally de-allocate the std::string's own allocated memory, and it would not solve the problem of having to de-allocate your original allocated memory.

Either use std::string throughout (preferred!) or capture the pointer inside main first:

int main()
{
   auto cstr = get_data(...);
   std::string data(cstr);
   free(cstr);
}

Trouble is, this isn't exception-safe, which is why we have nice things like std::string in the first place. It can be solved with some liberal try and catch but it'll be ugly.

Also, since you already have get_data, presumably for a reason, you might consider a string_view over the actual memory that you already allocated, unless you really need data to be an owning copy.

int main()
{
   auto cstr = get_data(...);
   std::string_view data(cstr);  // no copy! just features
   free(cstr);
}

(Comments elsewhere indicate that this may be what you really wanted.)

Now experiment with having get_data return something with clear ownership & lifetime semantics (std::unique_ptr? std::vector? std::string? .. lol) and you're golden.

Upvotes: 2

NathanOliver
NathanOliver

Reputation: 180935

Once you do

std::string data(get_data(...));

there is no way to get the pointer back that get_data() returned so you will leak that memory. To fix this just have get_data() return a std::string in the first place so you don't have to worry about memory management at all. That would give you

std::string get_data(...) {
    std::string data(length, '\0');
    load_c_string_with_my_c_function(data.data(), length, input); // requires C++17
    // load_c_string_with_my_c_function(&data[0], length, input); // use this for pre-C++17 compilers
    return data;
}

and now no memory leak. If you can't do this then you need to capture the pointer, use it to initialize the string, and then free the pointer like

char* ret = get_data(...);
std::string data(ret);
free(ret);

Upvotes: 5

Alan Birtles
Alan Birtles

Reputation: 36469

You can't delete the pointer, you aren't keeping a reference to it. You need to do:

int main() {
   char* cstr = get_data(...);
   std::string data(cstr);
   free(cstr);
   return 0;
}

Or much better write your data into the string directly:

std::string get_data(...) {
    std::string data(length, '\0');
    load_c_string_with_my_c_function(&data[0], data.size(), input);
    return data;
}

You may need to add 1 to the length of the std::string and/or pass data.size()-1 to load_c_string_with_my_c_function depending on the specification of the length parameter of load_c_string_with_my_c_function.

Upvotes: 1

Related Questions