views:

102

answers:

6

That's basically the question. If I have a pointer int *a = &someIntVar and I do not delete it over the course of the program, does it stay in memory after the program has terminated? Is this a case of data fragmentation?

EDIT:

My mistake for using a bad example. So int *a = new int[100]; never gets deleted, and even if it gets deleted, an answer says that the pointee is deleted, not the pointer. Yet pointers also have a length. So the question is, on a Windows or Linux OS, does it automatically clean up after pointers? (Assume C++)

+4  A: 

Since you have not newed this pointer, you are not leaking memory.

Were you to do int* a = new int; and not delete a, then you would leak a.

As a rule of thumb, the number of news should equal the number of deletes.

When someIntVar goes out of scope, the stack is unwound and its memory will be freed and a will be left dangling, of course.

Johnsyweb
But does that actually mean the address in memory is still allocated even though the program is terminated?
SoulBeaver
@Soul, no allocation has been done in your example, so no memory is kept reserved.
Péter Török
When your program is terminated, the OS cleans up after it. No memory is left allocated.
Jurily
+4  A: 

No, all memory allocated by the process is usually freed when the process terminates. But this may not be the case for stuff like file handles or graphics resources (i.e. in Win32 device context handles, bitmaps etc.).

humbagumba
File handles and GDI resources are released when process ends in current Windows versions. But valid point still: the same is not true for all resources.
Konrad Rudolph
Didn't know that this was also the case for file handles... good to know! But in older windows version, it was a very easy way to make your windows look very funny by leaking lots of GDI resources :)
humbagumba
+1  A: 

One confusing fact about delete p is that it does not actually delete p, but *p. That is, you don't delete the pointer, but the pointee. Whenever you see delete, you should think of it as delete_what_is_pointed_to_by. Oh yeah, and only delete what you new.

FredOverflow
+1  A: 

Do not properly deleted pointers fragment memory?

No. Lots of memory allocations and releases will fragment memory.

Here's an intuitive explanation of memory allocation (it is more complex than that and my example is naive at best and ignores lots of issues, but it should provide you with some idea).

Memory allocation usually happens in (at least) two steps:

  1. The OS allocates blocks of memory for the application.

  2. The application allocates memory from the available blocks for it's own use.

If the application uses all it's available memory (or it cannot allocate anymore), the OS will allocate more memory for the application. This is done transparently to the application, but it takes time (that's why memory allocations are slow).

When the application releases memory, the addresses/blocks are marked as free and will be reused on subsequent allocation requests (new/malloc/realloc/etc) by the application.

Memory fragmentation happens when the blocks of memory allocated to the application become fragmented (some fragments are allocated and some free).

For example:

int *a = new int;
int *b = new int;
int *c = new int;
int *d = new int;
int *e = new int;
int *f = new int;
// if the memory blocks for the pointers were allocated contiguously,
// the heap will look like this:
// [ a ][ b ][ c ][ d ][ e ][ f ][ free memory ... ]

// sometime later:
delete b;
delete d;
delete e;
// same memory block will look like this:
// [ a ][free][ c ][free][free][ f ][ free memory ... ]

For the sake of simplicity, let's say your application starts with 1000 bytes of memory available). If in a first step you allocated 200 int* (200 different variables) you'd have 200 x 4=800 bytes allocated, 200 bytes free.

If you wanted to allocate (in a second step) new int[100] more (one pointer, 400 more bytes), you wouldn't have enough memory available and the application would have to request more from the OS. You'd need at least 200 more bytes in your current block, or a new block of at least 400 bytes from the OS).

If you deleted memory allocated in step 1 to make space for allocating in step 2, it would be critical what memory you deleted:

  • If you deleted the last allocated pointers - you'd need to delete the last 50 pointers (50x4 = 200) - you'd have 200 bytes released + 200 unalocated = 400 needed). OK

  • If you deleted every 2nd pointer allocated at step 1 (or the first 50 pointers for that matter) you'd have 400 bytes available, but fragmented and no 400 bytes of continuous memory available. Your allocation in step 2 would fail, due to the fragmented memory.

My mistake for using a bad example. So int *a = new int[100]; never gets deleted, and even if it gets deleted, an answer says that the pointee is deleted, not the pointer. Yet pointers also have a length.

When you have int *a = new int[100]; you have here two parts:

  • The memory for a (the pointer itself) is 4 bytes (assuming a 32 bit architecture) allocated on the stack.

  • The memory pointed to by a is 400 bytes, allocated on the heap.

The heap memory will be released when you call delete[]a;. The stack memory (for the pointer itself) will be released to the available stack space when a* goes out of scope.

You only need to concern yourself with deleting the heap memory. The stack memory is released/reused as necessary by the program itself.

utnapistim
A: 

Hi SoulBeaver,

Try this on whatever OS you are using:

  1. Begin by observing the process memory footprint. Use top in Linux and Task Manager in Windows.
  2. Allocate a memory of 100000 as in int* p = new int[100000];
  3. Observe the memory footprint of the process. It is bound to increase by at least 100k*4 bytes. Now look into the 'free' memory left for use for other processes.
  4. Let the program run its course, do not delete anything. Post execution the space is returned to the system -- you should see available memory for use in other programs now go up.

As a side note, do not assume that if you do a delete []p; in the middle of the code your 100k*4 is immediately returned to the system. That may or may not be true -- Linux for e.g. has its own memory manager which takes such decisions.

Arpan

Fanatic23
+1  A: 

After int *a = new int[100]; you're using sizeof(a) + sizeof(int[100]) bytes of memory. After delete a, you're still using sizeof(a) bytes of memory. This is logical: you could write a = new int[50]; next. The memory of a is only released when a itself goes out of scope. If a is a global, this would be at program termination.

MSalters