0

I've just started playing with C++ (familiar with other languages) and I was wondering something.

When creating a dynamic sized array for example with new, why does it not get removed when it is out of scope, but an array with a fixed size does get removed?

E.g with the following code:

int foo()
{
    int baz[5]; // Gets removed out of scope
    int *bar = new int[5]; // Does not get removed, becomes a leak
}

Since both baz and bar are a pointer to the beginning of an array, can't the "runtime environment" apply the same technique (detect if something is out of scope, and delete it when it does) to something with a fixed size as a dynamic size?

What is the difference that it cannot do such a thing.

Matthijn
  • 3,126
  • 9
  • 46
  • 69
  • 3
    If you throw the hardware out of the window it is cleared by garbage collection (eventually) –  Jan 28 '14 at 14:48
  • "Since both baz and bar are a pointer" - wrong. `baz` is an array. – Mike Seymour Jan 28 '14 at 14:48
  • Doesn't baz just point to the beginning of an array? I could do int *foo = baz; -- and that would work just fine, that is where I "got that conclusion from" -- the location in memory and the value of both baz and foo are identical then when you compare them. -- If you "cout" baz it's value and it memory's address, it looks like a pointer to me. The value of baz is the memory location beginning of the beginning of the array. – Matthijn Jan 28 '14 at 14:52
  • This is C++, not Java - there is no "runtime environment" in the sense you're thinking. – The Forest And The Trees Jan 28 '14 at 14:53
  • 1
    @Matthijn: No, `baz` is an array. Arrays can be converted to pointers when necessary; but the array itself is an automatic variable, destroyed automatically. Your introductory book should explain exactly how arrays and pointers work. – Mike Seymour Jan 28 '14 at 14:54
  • @Matthijn An array is easily *converted* into a pointer to the first element, but it's a separate entity. See [Is array name a pointer in C?](http://stackoverflow.com/q/1641957/395760). –  Jan 28 '14 at 14:54

5 Answers5

7

Why does dynamic memory not get cleaned when it is out of scope

Because the purpose of dynamic memory is to be allocated past the end of scope. Dynamic memory is used when you need to allocate memory in one scope, then use and de-allocate it in another scope.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
utnapistim
  • 26,809
  • 3
  • 46
  • 82
  • Unfortunately there are cases where you need the dynamic allocation, but do not need the thing to outlive the scope. Since the language doesn't cater for that, we need to use the std library or other mechanisms to make sure there is no mess left to clean up. – juanchopanza Jan 28 '14 at 14:52
2

When creating a dynamic sized array for example with new, why does it not get removed

Because that is the main purpose of new: to allow you to control when the object is destroyed, which might be outside the scope of its creation.

(Dynamic allocation is also needed in other cases - to create arrays whose size or objects whose type isn't known at compile time, or which might be too big for the stack - since the language doesn't directly provide separate mechanisms for these cases. In that case, you can use a smart pointer or container to bind the objects' lifetimes to a scope.)

Since both baz and bar are a pointer to the beginning of an array

No they're not. baz is an array; it's destroyed when it goes out of scope. bar is a pointer to an array; it's destroyed, but the array it points to isn't.

can't the "runtime environment" apply the same technique

No. In general, there's no way to know whether a pointer points to a dynamic object. Even if there were, there's no way to know whether there are other references to it which should remain valid after this pointer is destroyed.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
1

Because the fixed size array is allocated in the function's stack and the dynamic one is allocated in the program's heap. The function stack is the memory space used to store your local variables. The stack is automatically free'd when the function end is reached. The heap is different, it's free'd once the program is closed.

Linblow
  • 449
  • 5
  • 7
  • I think this answer is nearing what I'm asking for, but now the question is. Why is there a difference between the heap and stack, (what is the difference). And why is one (dynamic) placed in the heap, and "fixed" placed on the stack. – Matthijn Jan 28 '14 at 14:57
  • The purpose of the stack memory is to store the variables local to the function scope. As utnapistim said, the purpose of dynamic memory is to be allocated past the end of scope: that's the program's heap memory. When you allocate space in the heap from a function, the allocated space remains usable after the function call. You couldn't do that with the stack. – Linblow Jan 28 '14 at 15:04
  • 1
    @Matthijn: Why is there a difference? Because sometimes you want the flexibility to choose when to destroy something, and sometimes you want the convenience of automatic destruction. So the language provides both automatic and dynamic storage duration (as well as static and thread-local) to give you that choice. The "stack" and "heap" are implementation details to provide those behaviours. – Mike Seymour Jan 28 '14 at 15:04
1

Dynamic memory is not deallocated automatically at the end of scope because the very purpose of dynamic memory is to have more control. You may want to deallocate at the end of the same scope where it was allocated, but you may want to deallocate somewhere else - it all depends on the design of your program.

Wojtek Surowka
  • 20,535
  • 4
  • 44
  • 51
  • If you would want to have some variables live beyond the scope of the function. You could just declare them outside the scope of the function? That would make sense to me. You won't be even able to reach "bar" unless you know it's address, or return that. But that is not always needed. – Matthijn Jan 28 '14 at 14:54
  • Variables declared outside of functions are created when program starts and destroyed when it ends. Normally more control is needed, you may want to create and destroy when it is needed. – Wojtek Surowka Jan 28 '14 at 15:02
1

The thing that does out of scope is one pointer to the memory, not the memory itself (it doesn't have a scope, just a life time). You wouldn't want to free memory whenever any pointer to it dies - virtually always you want to hand out temporary pointers (e.g. pass them to other functions), return a pointer from a function, store a copy of the pointer in some other places, etc.

In other words, in the course of using dynamically allocated memory you'd necessarily create and destroy many, many pointers to that memory. You wouldn't want most of those pointers to take the memory with them, only the last pointer should be used to free the memory. Any earlier and you get dangling pointers; any later and you don't have a pointer any more and can't free it at all.

There are ways to couple memory mangement to the life of a pointer, including the ability to transfer ownership: Returning the pointer, moving it from one variable to another, etc. This is a so-called smart pointers, specifically unique_ptr.

However, this is not suitable as the only pointer type, you still need non-owning pointers for all the aforementioned uses (handing out temporary referenced without freeing the memory afterwards). In addition, this idea (or at least its adoption into the mainstream) predates C++, as far as I know. It definitely predates C, which means C++ would need to keep raw pointers even if Bjarne had been born with innate mastership of smart pointers.