My first question is does the memory allocated by new in a function gets automatically deleted(deallocated) when the function ends.
int* foo()
{
int *a = new int; //memory allocated for an int
*a = 3;
return (a);
}//function ends -- is memory for integer still allocated.
If the memory is de-allocated automatically after the function ends, then shouldn't my next code give some error relating to accessing the memory which does not belong to me.
int main()
{
int *x = foo();
cout<<*x;
}
No it certainly does not. Every new has to be balanced with a delete. (And, to avoid any future doubt, any new[] has to be balanced with a delete[]).
There are constructs in C++ that will allow the effective release of memory once a container object has gone out of scope. Have a look at std::shared_ptr and std::unique_ptr.
No, the memory is not deallocated.
You should deallocate it manually with delete a;
In languages like Java or C# there is a so called Garbage Collector that handles memory deallocation when it finds out that some data is not longer needed. Garbage Collection can be used with C++, but it's not standard and in practice rarely used.
There are, however, other mechanisms you could use to automate deallocation of memory. Shared pointers are one of them. They introduce additional overhead. In regular C++ code usually the programmer is responsible for managing the memory (allocating and deallocating) manually. For beginners it's important to learn the basics before switching to more advanced mechanisms.
This is a bad practice to allocate dynamically from within a function and depend on the mercy of some other function to deallocate. Ideally, the caller should allocate space, pass that to the calling function and caller would deallocate when not in use.
void foo(int * a)
{
// a is pre-allocated by caller
*a = 3;
}//function ends -- caller takes care of allocation and deallocation
int main()
{
int *x = new int; // memory allocated for an int by caller
foo(x); // pass x as argument
cout << *x;
delete x; // deallocate, not required any more
return 0;
}
No, it is your responsibility to procure deallocation:
int *i = new int;
delete i;
However, the above code will sooner or later evolve into something that is almost impossible to make exception-safe. Better do not use pointers at all, or if you really must, use a smart pointer which will free the memory for you at the right moment:
std::shared_ptr<int> i (new int);
*i = 0xbeef;
return i;
There exist other smart pointers with different ownership semantics.
For most real world application, any imposed or assumed overhead introduced by smart pointers usually gets weight up easily against more expensive (I really mean money-saving) stuff like maintainability, extensibility, exception safety (where all there intermix into the other two).
Never forget that there exist alternatives to pointers, depending on the situation:
standard containers: If you need things like array
smart pointers: If you really need a pointer
references: Which you cannot forget to deallocate
plain objects: No pointers at all. Rely on copying and moving, which usually makes for a high degree of maintainability, extensibility, exception safety and performance. In C++, this should be your default choice.
As above, no raw pointers are never automatically deleted. This is why we don't use raw pointers for controlling lifetimes. We use smart pointers.
Here's your code snippet written correctly in modern c++:
std::unique_ptr<int> foo()
{
return std::unique_ptr<int>(new int(3));
// or std::make_unique<int>(3) for c++14
// function will either std::move the unique_ptr or emplace it efficiently
}
int main()
{
// x will either be created in-place or move-constructed by foo()
std::unique_ptr<int> x = foo();
// potential bug! pointers can be null
if (x) {
std::cout << *x;
}
else {
std::cout << "x is null\n";
}
}
Related
What I understand from RAII is whenever you need to allocate memory manually with new etc. you need to free it too. So, instead of freeing it manually, you should create classes with constructor and destructor to do the job.
So, what are the following people talking about?
From: The meaning of the term - Resource Acquisition Is Initialization
The problem is that int * p = malloc(1000); is also initialization of an (integer) object, but it's not the kind of initialization we mean in the context of RAII.
...
#Fred: Indeed. int* is not a RAII type because it doesn't do cleanup. So it's not what RAII means, even though it is what RAII literally says.
Well, I know malloc is used in C, and new is used in C++.
Using malloc per se is not RAII because the resources are not freed when the variable goes out of scope, causing leaks of memory. You can make it RAII if you wrap this inside a class and free the resources in the destructor, because local class instances do die when they go out of scope. However, it should be noted what is being discussed here: the int * type is not RAII, and if you enclose it in a RAII type it still isn't. The wrapper doesn't make it RAII, so the RAII type here is the wrapper, not the pointer itself.
As requested in the comments: RAII stands for Resource Acquisition Is Initialisation and it's a design paradigm that combines the allocation of resources with the initialisation and destruction of objects. You don't seem far from understanding it: when an object is instantiated it allocates all the necessary resources (memory, file descriptors, streams, and so on) and frees them when it goes out of scope or the object is otherwise destructed. This is a common paradigm in C++ because C++ classes are RAII (that is, they die when they go out of scope) and as such it's easy to guarantee proper cleanup. The obvious upside being that you don't need to worry about manual cleanup and tracking variable lifetime.
On a related note, notice that this refers to stack allocation, not heap. What this means is that whatever the means you use for allocation (new/malloc vs delete/free) it still isn't RAII; memory that is allocated dynamically does not get magically freed, that's a given. When a variable is allocated on the stack (local variables) they are destroyed when the scope dies.
Example:
class MyObject
{
public:
MyObject()
{
// At this point resources are allocated (memory, files, and so on)
// In this case a simple allocation.
// malloc would have been just as fine
this->_ptr = new int;
}
~MyObject()
{
// When the object is destructed all resources are freed
delete this->_ptr;
}
private:
int * _ptr;
};
The previous sample code implements a RAII wrapper over a native pointer. Here's how to use it:
void f()
{
MyObject obj;
// Do stuff with obj, not including cleanup
}
In the previous example the int pointer is allocated when the variable is instantiated (at declaration time) and freed when the f call terminates, causing the variable to go out of scope and calling its destructor.
Note: As mentioned in the comments by Jarod42 the given example does not conform to the rule of 3 or the rule of 5, which are common thumb rules in C++. I would rather not add complexity to the given example, and as such I'll complete it here. These rules indicate that, if a method from a given set is implemented, then all methods of the set should be implemented, and those methods are the copy and move constructors, the assignment and move operators, and the destructor. Notice at first that this is a general rule, which means that is not mandatory. For instance, immutable objects should not implement assignment and move operators at all. In this case, if the object is to implement these operators it would probably imply reference counting, as multiple copies of the resource exist the destructor must not free the resources until all copies are destroyed. I believe that such an implementation would fall out of scope and as such I'm leaving it out.
By example
NOT RAII:
void foo()
{
int* p = malloc(sizeof(int) * N);
// do stuff
free(p);
}
also NOT RAII:
void foo()
{
int* p = new int[N];
// do stuff
delete[] p;
}
RAII:
struct MyResourceManager
{
int* p;
MyResourceManager(size_t n) : p(malloc(sizeof(int) * n)) { }
~MyResourceManager() { free(p); }
};
void foo()
{
MyResourceManager resource(N);
// doing stuff with resource.p
}
Also RAII (better):
struct MyResourceManager
{
int* p;
MyResourceManager(size_t n) : p(new int[n]) { }
~MyResourceManager() { delete[] p; }
};
void foo()
{
MyResourceManager resource(N);
// doing stuff with resource.p
}
Also RAII (best for this use case):
void foo()
{
std::unique_ptr<int[]> p(new int[N]);
// doing stuff with p
}
RAII is not use of operator new nor is it use of malloc().
It essentially means that, in the process of initialising an object, all resources that object needs to function are allocated. The counterpart requirement is that, in the process of destroying the object, that the resources it has allocated are released.
The concept applies to memory (most commonly), but also to any other resource that needs to be managed - file handles (opened in initialisation, closed when done), mutexes (grabbed in initialisation, released when done), communication ports, etc etc.
In C++, RAII is typically implemented by performing initialisation in constructors of an object, and the release of resources is done in the destructor. There are wrinkles such as other member functions possibly reallocating (e.g. resizing a dynamically allocated array) - in those cases, the member functions must ensure they do things in a way to ensure all resources allocated are appropriately released when the destructor is done. If there are multiple constructors, they need to do things consistently. You'll see this described as something like the constructor setting a class invariant (i.e. that resources are allocated correctly), member functions maintaining that invariant, and the destructor being able to clean up because the invariant is maintained.
The advantage of RAII - if done right - is that non-static variable lifetime is managed by the compiler (when an object goes out of scope, its destructor is invoked). So, the resources will be cleaned up correctly.
However, the requirement is always that the destructor does the cleanup (or that data members of the class have their own destructors that do the required cleanup). If constructor initialises an int * using malloc(), then it is not enough to assume the destructor will clean up - the destructor must pass that pointer to free(). If you don't do that, the C++ compiler will not magically find some way to release the memory for you (the pointer will no longer exist when the destructor is done, but the allocated memory it pointed to will not be released - so the result is a memory leak). C++ does not inherently use garbage collection (which is a trap for people used to garbage collected languages assuming that garbage collection will occur).
And it is undefined behaviour to use malloc() to allocate memory, and operator delete in any form to release it.
It is generally preferable to not use malloc() and free() in C++, because they do not work well with object construction and destruction (invoking constructors and destructors). Use operator new instead (and for whatever form of operator new you use, use the corresponding operator delete). Or, better yet, use standard C++ containers (std::vector, etc) as much as possible to avoid the need to worry about manually releasing memory you allocate.
Destruction of int* doesn't release the resources. It isn't safe to just let it go out of scope, so it isn't RAII.
The int * could be be a member of a class that deletes the int* in its destructor, which is essentially what unique_ptr of an int does. You make things like this RAII by wrapping them in code that encapsulates the deletion.
The discussion is about code that literally does initialization upon resource acquisition, but doesn't follow the RAII design.
In the shown example with malloc, 1000 bytes of memory are allocated (resource allocation) and a variable p (pointer to int) is initialized with the result (initialization). However, this is obviously not an example of RAII, because the object (of type int *) doesn't take care of the acquired resource in its destructor.
So no, malloc itself can not be RAII in some situations, it is an example of non-RAII code that nevertheless does "Initialization on Resource Acquisition" which might be confusing for new c++ programmers on first glance.
In C++, unique_ptr represents a pointer that "owns" the thing it points to. You can supply the release function as second argument:
std::unique_ptr<int[], std::function<void(void*)>>
p( (int *)malloc(1000 * sizeof(int)), std::free );
Of course, there's not much reason to do this instead of just using new (when the default deleter delete will do the right thing).
Yes, you can deal with int * p = malloc(1000); using the RAII paradigm. Smart pointers and std::vector use a very similar technique though they don't probably use malloc and prefer to use new instead.
Here's a very simplistic look at what one can do with malloc. MyPointer is far from being useful in a real application. Its only purpose is to demonstrate the principle of RAII.
class MyPointer
{
public:
MyPointer(size_t s) : p(malloc(s)) {}
~MyPionter() { free(p); }
int& operator[](size_t index) { return p[index]; }
private:
int* p;
};
int main()
{
// By initializing ptr you are acquiring resources.
// When ptr gets destructed, the resource is released.
MyPointer ptr(1000);
ptr[0] = 10;
std::cout << ptr[0] << std::endl;
}
The core idea behind RAII is:
Treat resource acquisition as though you are initializing an object.
Make sure the acquired resource(s) is(are) released when the object is destructed.
You can read more on RAII at Wikepedia.
So, what are the following people talking about?
What is RAII?
RAII in a nutshell is a very simple idea. It is the idea that no object may exist at all unless it is fully initialised.
Why is that good?
We now have a concrete guarantee that a 'half built' object cannot be accidentally used - because at no point in the logical flow of the program can it possibly exist.
How do we achieve it?
a) always manage resources (memory, files, mutex locks, database connections) in a class of their own which is specifically tailored to only managing that resource.
b) build complex logic out of collections of objects covered by [a]
c) Always throw if anything in the constructor fails (to guarantee that a failed object cannot exist)
d) if we are managing more than one resource in a class, we ensure that a failed construction cleans up the parts that have already been constructed (NOTE: this is hard [sometimes impossible], and why at this point you should be referred back to [a])
Sounds hard?
Initialising your objects completely in the initialiser list, while wrapping all external resources in a manager class (e.g. files, memory) achieves perfect RAII effortlessly.
What's the advantage?
Your program may now contain only logic which makes it easier to reason about and to read. The compiler will take care of all resource management perfectly.
Effortless Compound Resource Management
An example of RAII that's hard without manager classes and easy with them?
struct double_buffer
{
double_buffer()
: buffer1(std::nullptr) // NOTE: redundant zero construction
, buffer2(std::nullptr)
{
buffer1 = new char[100]; // new can throw!
try {
buffer2 = new char[100]; // if this throws we have to clean up buffer1
}
catch(...) {
delete buffer1; // clean up buffer1
throw; // rethrow because failed construction must throw!
}
}
// IMPORTANT!
// you MUST write or delete copy constructors, move constructor,
// plus also maybe move-assignment or move-constructor
// and you MUST write a destructor!
char* buffer1;
char* buffer2;
};
now the RAII version:
struct double_buffer
{
double_buffer()
: buffer1(new char[100]) // memory immediately transferred to manager
, buffer2(new char[100]) // if this throws, compiler will handle the
// correct cleanup of buffer1
{
// nothing to do here
}
// no need to write copy constructors, move constructor,
// move-assignment or move-constructor
// no need to write destructor
std::unique_ptr<char[]> buffer1;
std::unique_ptr<char[]> buffer2;
};
How does it improve my code?
some safe code that uses RAII:
auto t = merge(Something(), SomethingElse()); // pretty clear eh?
t.performAction();
the same code that does not use RAII:
TargetType t; // at this point uninitialised.
Something a;
if(a.construct()) {
SomethingElse b;
if (b.construct()) {
bool ok = merge_onto(t, a, b); // t maybe initialised here
b.destruct();
a.destruct();
if (!ok)
throw std::runtime_error("merge failed");
}
else {
a.destruct();
throw std::runtime_error("failed to create b");
}
}
else {
throw std::runtime_error("failed to create a");
}
// ... finally, we may now use t because we can (just about) prove that it's valid
t.performAction();
The difference
The RAII code is written solely in terms of logic.
The non-RAII code is 40% error handling and 40% lifetime management and only 20% logic. Furthermore, the logic is hidden in amongst all the other garbage, making even these 11 lines of code very hard to reason about.
Never using
new
delete
release
and preferring to use
std::make_unique
std::unique_ptr
std::move
reset (redundant)
should morally result in no memory leaks: new'ed pointers are only ever created inside smart pointers, from which they can never escape, because we have disallowed use of release.
One may therefore be tempted into using this coding style, and then never bother checking for memory leaks again - no matter where exceptions may be thrown from, the RAII semantics of the smart pointers should always clean up any dangling pointers as the stack is unwound.
Except C++ is full of nasty surprises. From experience of having my assumptions repeatedly smashed by gotw, I can't help but think that there might be some corner-case which manages to cause a memory leak anyway. Even worse, there might be an obvious way of releasing ownership of the pointer other than release itself. Or another smart pointer class without an explicit constructor which could accidentally ingest the raw pointer obtained via get, leading to double frees...
Are there any loopholes? If there are, can they be fixed by adding some more simple restrictions? (not allocating any memory doesn't count!) And if a set of coding guidelines that prevents all types of memory errors can be reached, would it be okay to completely forget about the details of memory management?
I thought cyclic references were only a problem with std::shared_ptr...
struct X
{
std::unique_ptr<X> x;
};
void leak()
{
auto x = std::make_unique<X>();
x->x = std::move(x);
}
This can be fixed by ensuring that there is no cycle in the graph of types formed by adding an edge from A to B if and only if A contains a member std::unique_ptr<C> where C is a base of B.
struct evil {
std::shared_ptr<evil> p; // Alternatively unique_ptr
};
void foo() {
auto e = std::make_shared<evil>(); // Alternatively make_unique
e->p = e; // Alternatively std::move(e)
}
int main() {
for (unsigned i = 1; i != 0; ++i) {
foo();
if (i % 100000000)
std::cout << "I leak\n";
}
}
the above program obeys your restrictions, and leaks like a sieve.
On top of that, undefined behavior can cause leaks.
would it be okay to completely forget about the details of memory management?
I'd say the answer to this is going to be no in programming for the foreseeable future. Even in garbage collected languages today you can't forget about the details of memory management if you want a performant application.
Memory leaks still happen in garbage collected languages when programs accidentally hang onto references that are no longer needed. Following the rules you set out above for C++ would still be prone to the same issues and is even more likely to be an issue with uses of shared_ptr. Common errors of this type are hanging on to objects in a container or through observers for managed references in a garbage collected language or shared_ptr in C++.
There's no guarantee, there's so much that one can screw up ...
unions ... (Example)
union Devil {
std::unique_ptr<int> ptr;
int b;
Devil () {}
~Devil () {
// no idea what I'm doing
}
};
Inheritance ... (Example)
struct Base {};
struct Derived : public Derived {
std::unique_ptr<int> ptr;
};
// later ...
std::unique_ptr<Base> p = std::make_unique<Derived>(42);
// oops
playing on the stack ...
int f1[10];
std::unique_ptr<int> p[2];
int f2[10];
// later ...
p[2] = std:: make_unique<int>(42);
// oops
... or more generally undefined behaviour. The above is pretty sure only the top of the iceberg ...
I have a function foo like
myType** foo(){
myType **array = malloc( .... );
//Do some stuff
return array;
}
Here I have malloced , but did not free it as I am returning it . Will this cause a memory leak ? Should I explicitly free it in the calling function after I use it ?
It's a memory leak only if you don't free the memory (regardless where).
In this case, you should free it after the function is called and you're done with the pointer.
But this is the C way of doing it. In C++ you'd return a smart pointer, and use new instead of malloc.
With this type of function, the caller is the "owner" of the resources pointed at by the pointer. So the caller has to either free the resources, or pass them on to someone else who will.
In C++ one would favour returning a type that manages its own resources, for example an std::vector, or a smart pointer, that both takes care of resource de-allocation and makes the ownership clear.
See this example,and don't worry, read all about copy elision, particularly named return value optimization (NRVO).
std::vector<std::vector<SomeType>> foo()
{
std::vector<std::vector<SomeType>> tmp = ....;
// do some stuff
return tmp;
}
Memory leaks are caused by not freeing memory. As long as the memory will get freed at some point, then it isn't leaked. But if the pointer ever gets "lost" or if some sort of dependency loop causes a situation where the memory stays around even after it is no longer useful, then at that point you've created a leak.
Usually in this type of situation, you create a pattern like this:
void* mything_init() {
void *obj = malloc(LEN);
// do some initialization
return obj;
}
void mything_uninit(void* thing) {
// any teardown
free(thing);
}
For every mything that you _init, you must eventually call _uninit on that object. That is your responsibility as the user of that library. While as the writer of that library, you make sure that anything you allocate in the _init gets properly freed in _uninit.
This is a C pattern rather than a C++ pattern as malloc() is a C idiom. C++ uses new and delete, and this sort of work us usually done in a constructor/destructor pair.
I had issues about this problem for long time. I suggest you to read this wiki page:
Smart Pointers
In your case you can use unique_ptr. So you would be able to transfer the ownership of the pointer to the caller function.
unique_ptr<int> callee1()
{
std::unique_ptr<int> p1(new int(5));
return p1;
}
int main()
{
std::unique_ptr<int> result = callee1() ;
(*result)++; // Increase the value stored in the pointer
std::cout << "New Value: " << (*result) << std::endl;
result.reset() ;
}
Hope this code sniper helps you.
int* f()
{
int *p = new int[10];
return p;
}
int main()
{
int *p = f();
//using p;
return 0;
}
Is it true that during stack destruction when function return it's value some compilers (common ones like VS or gcc were implied when I was told that) could try to automatically free memory pointed by local pointers such as p in this example? Even if it's not, would I be able to normally delete[] allocated memory in main? The problem seems to be that information about exact array size is lost at that point. Also, would the answer change in case of malloc and free?
Thank you.
Only Local variables are destroyed-released.
In your case p is "destroyed" (released) , but what what p points to, is not "destroyed" (released using delete[]).
Yes you can, and should/must use a delete[] on your main. But this does not imply using raw pointers in C++. You might find this e-book interesting : Link-Alf-Book
If you want to delete what a local variable points to when the function is "over" (out of scope) use std::auto_ptr() (only works for non-array variables though, not the ones which require delete[])
Also, would the answer change in case
of malloc and free?
Nope, but you should make sure that you do not mix free()/new/delete/malloc(). The same applies for new/delete[] and new[]/delete.
No, they won't free or delete what your pointer points to. They will only release the few bytes that the pointer itself occupies. A compiler that called free or delete would, I believe, violate the language standard.
You will only be able to delete[] memory in main if you a pointer to the memory, i.e., the result from f(). You don't need keep track of the size of the allocation; new and malloc do that for you, behind the scenes.
If you want memory cleaned up at function return, use a smart pointer such as boost::scoped_ptr or boost::scoped_array (both from the Boost collection of libraries), std::auto_ptr (in the current C++ standard, but about to be deprecated) or std::unique_ptr (in the upcoming standard).
In C, it's impossible to create a smart pointer.
Is it true that during stack destruction when function return it's value some compilers (common ones like VS or gcc were implied when I was told that) could try to automatically free memory pointed by local pointers such as p in this example?
Short Answer: No
Long Answer:
If you are using smart pointers or container (like you should be) then yes.
When the smart pointer goes out of scope the memory is released.
std::auto_ptr<int> f()
{
int *p = new int;
return p; // smart pointer credated here and returned.
// p should probably have been a smart pointer to start with
// But feeling lazy this morning.
}
std::vector<int> f1()
{
// If you want to allocate an array use a std::vector (or std::array from C++0x)
return std::vector<int>(10);
}
int main()
{
std::auto_ptr<int> p = f();
std::vector<int> p1 = f1();
//using p;
return 0; // p destroyed
}
Even if it's not, would I be able to normally delete[] allocated memory in main?
It is normal to make sure all memory is correctly freed as soon as you don't need it.
Note delete [] and delete are different so be careful about using them.
Memory allocated with new must be released with delete.
Memory allocated with new [] must be released with delete [].
Memory allocated with malloc/calloc/realloc must be released with free.
The problem seems to be that information about exact array size is lost at that point.
It is the runtime systems problem to remember this information. How it is stored it is not specified by the standard but usually it is close to the object that was allocated.
Also, would the answer change in case of malloc and free?
In C++ you should probably not use malloc/free. But they can be used. When they are used you should use them together to make sure that memory is not leaked.
You were misinformed - local variables are cleaned up, but the memory allocated to local pointers is not. If you weren't returning the pointer, you would have an immediate memory leak.
Don't worry about how the compiler keeps track of how many elements were allocated, it's an implementation detail that isn't addressed by the C++ standard. Just know that it works. (As long as you use the delete[] notation, which you did)
When you use new[] the compiler adds extra bookkeeping information so that it knows how many elements to delete[]. (In a similar way, when you use malloc it knows how many bytes to free. Some compiler libraries provide extensions to find out what that size is.)
I haven't heard of a compiler doing that, but it's certainly possible for a compiler to detect (in many cases) whether the allocated memory from the function isn't referenced by a pointer anymore, and then free that memory.
In your case however, the memory is not lost because you keep a pointer to it which is the return value of the function.
A very common case for memory leaks and a perfect candidate for such a feature would be this code:
int *f()
{
int *p = new int[10];
// do something that doesn't pass p to external
// functions or assign p to global data
return p;
}
int main()
{
while (1) {
f();
}
return 0;
}
As you can notice, the pointer to the allocated memory is lost and that can be detected by the compiler with absolute certainty.
I know this won’t work because the variable x gets destroyed when the function returns:
int* myFunction()
{
int x = 4;
return &x;
}
So how do I correctly return a pointer to something I create within the function, and what do I have to take care with? How do I avoid memory leaks?
I've also used malloc:
int* myFunction2()
{
int* x = (int*)malloc(sizeof int); *x = 4; return x;
}
How do you correctly do this - in C and C++?
For C++, you can use a smart pointer to enforce the ownership transfer. auto_ptr or boost::shared_ptr are good options.
Your second approach is correct. You just need to clearly document that the caller "owns" the result pointer, and is responsible for freeing it.
Because of this extra complexity, it is rare to do this for "small" types like int, though I'm assuming you just used an int here for the sake of an example.
Some people will also prefer to take a pointer to an already allocated object as a parameter, rather than allocating the object internally. This makes it clearer that the caller is responsible for deallocating the object (since they allocated it in the first place), but makes the call site a bit more verbose, so it's a trade-off.
For C++, in many cases, just return by value. Even in cases of larger objects, RVO will frequently avoid unnecessary copying.
One possibility is passing the function a pointer:
void computeFoo(int *dest) {
*dest = 4;
}
This is nice because you can use such a function with an automatic variable:
int foo;
computeFoo(&foo);
With this approach you also keep the memory management in the same part of the code, ie. you can’t miss a malloc just because it happens somewhere inside a function:
// Compare this:
int *foo = malloc(…);
computeFoo(foo);
free(foo);
// With the following:
int *foo = computeFoo();
free(foo);
In the second case it’s easier to forget the free as you don’t see the malloc. This is often at least partially solved by convention, eg: “If a function name starts with XY, it means that you own the data it returns.”
An interesting corner case of returning pointer to “function” variable is declaring the variable static:
int* computeFoo() {
static int foo = 4;
return &foo;
}
Of course this is evil for normal programming, but it might come handy some day.
C++ approach to avoid memory leaks. (at least when You ignore function output)
std::auto_ptr<int> myFunction() {
std::auto_ptr<int> result(new int(4));
return result;
}
Then call it:
std::auto_ptr<int> myFunctionResult = myFunction();
EDIT: As pointed out by Joel. std::auto_ptr has it's own drawbacks and generally should be avoided.
Instead std::auto_ptr You could use boost::shared_ptr (std::tr1::shared_ptr).
boost::shared_ptr<int> myFunction() {
boost::shared_ptr<int> result(new int(5));
return result;
}
or when use C++0x conforming compiler You can use std::unique_ptr.
std::tr1::unique_ptr<int> myFunction() {
std::tr1::unique_ptr<int> result(new int(5));
return result;
}
The main difference is that:
shared_ptr allows multiple instances of shared_ptr pointing to the same RAW pointer. It uses reference counting mechanism to ensure that memory will not be freed as long as at least one instance of shared_ptr exist.
unique_ptr allows only one instance of it holding pointer but have true move semantic unlike auto_ptr.
In C++, you should use new:
int *myFunction()
{
int blah = 4;
return new int(blah);
}
And to get rid of it, use delete:
int main(void)
{
int *myInt = myFunction();
// do stuff
delete myInt;
}
Note that I'm invoking the copy constructor for int while using new, so that the value "4" is copied onto the heap memory. The only way to get a pointer to something on the stack reliably is to copy it onto the heap by invoking new properly.
EDIT: As noted in another answer, you will also need to document that the pointer needs to be freed by the caller later on. Otherwise you might have a memory leak.
There is another approach - declare x static. In this case it will be located in data segment, not on stack, therefore it is available (and persistent) during the program runtime.
int *myFunction(void)
{
static int x = 4;
return &x;
}
Please note that assignment x=4 will be performed only on first call of myFunction:
int *foo = myFunction(); // foo is 4
*foo = 10; // foo is 10
*foo = myFunction(); // foo is 10
NB! Using function-scope static variables isn't tread-safe technique.
Your second code snippet is correct.
To help avoid memory leaks, I let the coding conventions help me.
xxxCreate() will allocate memory for xxx and initialize it.
xxxDelete() will destroy/corrupt xxx and free it.
xxxInit() will initialize xxx (never allocate)
xxxDestroy() will destroy/corrupt xxx (never free)
Additionally, I try to add the code to delete/destroy/free as soon as I add the code to create/init/malloc. It's not perfect, but I find that it helps me differentiate between items that need to be freed and those that don't, as well as reducing the likelihood that I will forget to free something at a later time.
Boost or TR1 shared pointers are generally the way to go. It avoids the copy overhead, and gives you semi-automatic deletion. So your function should look like:
boost::shared_ptr<int> myFunction2()
{
boost::shared_ptr<int> x = new int;
*x = 4;
return x;
}
The other option is just to allow a copy. That's not too bad if the object is small (like this one) or you can arrange to create the object in the return statement. The compiler will usually optimize a copy away if the object is created in the return statement.
I would try something like this:
int myFunction2b( int * px )
{
if( px )
{
*px = 4;
return 1;
}
// Choice 1: Assert or Report Error
// Choice 2: Allocate memory for x. Caller has to be written accordingly.
// My choice is 1
assert( 0 && "Argument is NULL pointer" );
return 0;
}
You're asking how to correctly return a pointer. That's the wrong question, because what you should be doing is using smart pointers rather than raw pointers. scoped_ptr and shared_ptr (available in boost and tr1) are good pointers to look at (e.g. here and here)
If you need the raw pointer for something (e.g. passing to a C function), the get() method will supply it.
If you must create raw pointers, e.g. for homework, then you can use malloc() (as you did) or new within a function, and hope you remember to de-allocate the memory (through free() and delete respectively) Or, in a slightly-less-likely-to-leak idiom, you can create the pointer with new, pass it to a function, and de-allocate with delete when you're done with it. Again, though, use smart pointers.