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.
问题:
回答1:
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.
回答2:
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!
回答3:
In C++, you would return a smart pointer, which clearly states (and enforces) that ownership has been transferred to the caller, and allows the caller to choose what to do with it. It also provides exception safety, preventing a memory leak if an exception (or just an early function return) causes the only pointer to the resource to go out of scope.
In C++03, std::auto_ptr
is the best choice here; in C++11, this is deprecated in favour of std::unique_ptr
.
回答4:
C Solution:
And what if fun() is part of library?
Your library api should then doccument the fact memory needs to freed by the caller.
You also should provide a free function for the same and mandate that user of the library should call it to free the allocation.
EDIT:
C++ Solution:
Since you edited to say that you are using C++, perhaps it is best to use smart pointers (std::tr1::shared_ptr
)to automatically handle the memory for you.
If you cannot use smart pointers for some reason using std::vector
is also a good choice.
回答5:
If you need the memory outside of the callee, it's pretty obvious that it is responsible to free up the memory, since you can't really free it in the callee. It's the same as new
and delete
- you simply must remember to free that memory. Make sure you document the fact that the caller is responsible for memory management.
回答6:
You have to document that memory is allocated and that the caller is responsible for freeing it. You can't free it yourself as you can't know the caller's intention. you'd be freeing it before use.
You could provide a cleanUp() method to be called and flush the memory but that relies on the caller still and you add complications around when it should be called.
The only real alternative is to set up a clever "reference counting" mechanism such as in Objective-C (see release and autorelease).