Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do you have to call delete for local variables of a function that are stored in the heap?

Suppose that you have the following function:

 void doSomething(){
    int *data = new int[100];
 }

Why will this produce a memory leak? Since I can not access this variable outside the function, why doesn't the compiler call delete by itself every time a call to this function ends?

like image 743
jsguy Avatar asked Mar 03 '15 13:03

jsguy


People also ask

What is the standard deletion operation on heap?

The standard deletion operation on Heap is to delete the element present at the root node of the Heap. That is if it is a Max Heap, the standard deletion operation will delete the maximum element and if it is a Min heap, it will delete the minimum element. Since deleting an element at any intermediary position in the heap can be costly, ...

Should local variables be allocated on the stack or heap?

Default to stack variables, period. One colleague argued that very big objects should be an exception and local variables of those should be allocated on the heap. He was wrong. It is unreasonable for the user of a class to need to know whether objects of that class are too big to be allocated on the stack, and how big “too big” actually is.

Can you delete pointers created on the heap using other functions?

So don’t just go deleting pointers arbitrary functions give you. Pointers created on the heap using other API than new usually also need to be deleted, but usually using a special function, not using delete. E.g. if you used malloc () to create memory, you need to delete it using the function free ().

What happens when you delete a variable in a class?

No errors throw, but I can access the variable without problems after deletion. Having a class with a method with delete this successfully deletes the object if it is allocated in the heap, but not if it is allocated in the stack (if it is in the stack, nothing happens). Your answer is actually relevant to the question.


2 Answers

Why will this produce a memory leak?

Because you're responsible for deleting anything you create with new.

Why doesn't the compiler call delete by itself every time a call to this function ends?

Often, the compiler can't tell whether or not you still have a pointer to the allocated object. For example:

void doSomething(){
    int *data = new int[100];
    doSomethingElse(data);
}

Does doSomethingElse just use the pointer during the function call (in which case we still want to delete the array here)? Does it store a copy of the pointer for use later (in which case we don't want to delete it yet)? The compiler has no way of knowing; it's up to you to tell it. Rather than making a complicated, error-prone rule (like "you must delete it unless you can figure out that the compiler must know that there are no other references to it"), the rule is kept simple: you must delete it.

Luckily, we can do better than juggling a raw pointer and trying to delete it at the right time. The principle of RAII allows objects to take ownership of allocated resources, and automatically release them when their destructor is called as they go out of scope. Containers allow dynamic objects to be maintained within a single scope, and copied if needed; smart pointers allow ownership to be moved or shared between scopes. In this case, a simple container will give us a dynamic array:

void doSomething(){
    std::vector<int> data(100);
} // automatically deallocated

Of course, for a small fixed-size array like this, you might as well just make it automatic:

void doSomething(){
    int data[100];
} // all automatic variables are deallocated
like image 155
Mike Seymour Avatar answered Sep 27 '22 19:09

Mike Seymour


The whole point of dynamic allocation like this is that you manually control the lifetime of the allocated object. It is needed and appropriate a lot less often than many people seem to think. In fact, I cannot think of a valid use of new[].

It is indeed a good idea to let the compiler handle the lifetime of objects. This is called RAII. In this particular case, you should use std::vector<int> data(100). Now the memory gets freed automatically as soon as data goes out of scope in any way.

like image 35
Baum mit Augen Avatar answered Sep 27 '22 20:09

Baum mit Augen