Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Freeing memory in caller or callee?

A function (Say "fun()") allocates memory and returns the pointer to allocated memory. How should I make sure I that this memory is released. I can't release it immediately in function "fun()" as it is returned to caller. And what if fun() is part of library? Whose responsibility it is to free memory. In case of fopen(), the memory is released by fclose(). But in my case, "fun()" is called repeatedly. So I can not wait till end to release the memory.

like image 916
Rahul Avatar asked Dec 07 '22 18:12

Rahul


2 Answers

The following is the answer for C, posted before the OP confessed to using C++. In that language, use RAII and smart pointers, as recommended by others.

If a function returns allocated memory, then the caller is responsible for deallocation and this must be stated in the function's documentation.

If more cleanup is needed then is offered by free, or such cleanup may to be needed in future versions of the library, then you should offer a cleanup function (like stdio does with fclose) that does the deallocation. If you can't predict whether extra cleanup may be necessary in the future, then it's a good idea to assume it will be at some point. Wrapping free is cheap.

Think of it as a form of symmetry: if the client gets a resource (object) from the library, then it is eventually responsible for handing it back to the library for disposal:

void use_the_foo_library()
{
    Foo *f = make_foo();
    if (f == NULL)
        ERROR();

    foo_do_bar(f);
    foo_do_baz(f);

    foo_destroy(f);
}

where in foolib 1.0, foo_destroy is just

void foo_destroy(Foo *p)
{
    free(p);
}

but in version 2.0, it may have grown to

void foo_destroy(Foo *p)
{
    fclose(p->logfile);
    free(p);
}

etc. This style is consistent with the opaque pointer design pattern. It also gives you the freedom of replacing malloc and free at any point with a special purpose memory allocator, such as a pool allocator, without having to change any client code.

like image 136
Fred Foo Avatar answered Dec 27 '22 00:12

Fred Foo


If it's C++, don't return a raw pointer to memory, return a smart pointer instead.

eg:

std::shared_ptr<TypePointedTo> data = fun();

That way, when the shared_ptr destructs it will automatically free the memory for you.

Or, if it's an array you want to return use a vector, again this will automatically free the memory for you:

std::vector<BYTE> data = fun();

Read the excellent comments, std::unique_ptr could be a better than std::shared_ptr in a lot of scenarios.

If it's C ... see other answers!

like image 29
Scott Langham Avatar answered Dec 27 '22 00:12

Scott Langham