3
int a = 0; 
int *b = malloc (sizeof(int));
b = malloc (sizeof(int));

The above code is bad because it allocates memory on the heap and then doesn't free it, meaning you lose access to it. But you also created 'a' and never used it, so you also allocated memory on the stack, which isn't freed until the scope ends.

So why is it bad practice to not free memory on the heap but okay for memory on the stack to not be freed (until the scope ends)?

Note: I know that memory on the stack can't be freed, I want to know why its not considered bad.

dfg
  • 777
  • 1
  • 8
  • 24
  • Variables on the stack are automatically 'freed' when they lose scope. Memory on the heap is never freed unless you free it explicitly. – Charlie Burns Nov 05 '13 at 15:33
  • 3
    One thing that isn't mentioned so far: stack allocation is faster than heap allocation, and heap allocation has bookkeeping overhead. Allocating every single variable on the heap would affect performance. So you get two different allocation methods - one that is designed for frequent short-lived allocations, and another that is designed for long-lived allocations. – DCoder Nov 05 '13 at 15:39
  • 2
    Just because ***stack*** and ***heap***, mentioned many times in the answers below, and are sometimes misunderstood terms, even amongst C programmers, ***[Here is a great conversation](http://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap)*** discussing that topic. – ryyker Nov 05 '13 at 19:23
  • @DCoder: Right about that, I've added that to my answer – Elias Van Ootegem Nov 06 '13 at 08:58

7 Answers7

8

The stack memory will get released automatically when the scope ends. The memory allocated on the heap will remain occupied unless you release it explicitly. As an example:

void foo(void) {
    int a = 0;
    void *b = malloc(1000);
}

for (int i=0; i<1000; i++) {
    foo();
}

Running this code will decrease the available memory by 1000*1000 bytes required by b, whereas the memory required by a will always get released automatically when you return from the foo call.

zoul
  • 102,279
  • 44
  • 260
  • 354
  • What if the whole program runs in one scope? Doesn't that mean the space is unreusable until the end of the program? Kinda like memory on the heap? – dfg Nov 05 '13 at 15:35
  • 1
    @dfg How would you "free" a variable allocated on the stack? Normally the compiler is smart enough to reuse memory of the stack if a variable isn't used any more (at least an optimizing compiler), so you shouldn't bother with that. – Axel Nov 05 '13 at 15:35
  • @Axel I know you can't free the variable, but why is that acceptable? – dfg Nov 05 '13 at 15:36
  • 4
    Memory leaks are not really acceptable... If you program doesn't need an allocated memory anymore, it has to be freed. – Joze Nov 05 '13 at 15:39
  • 1
    The top-level stack scope is usually only used for small amounts of memory. And there’s usually a strict size limit to the amount of memory you can allocate on the stack, making the problem a non-issue in practice. – zoul Nov 05 '13 at 15:39
  • The compiler cleans it up for you when the function is left. However, you are right that it is also seen as bad practice to have large variables (like huge arrays) on the stack because of the effect you mentioned. – Axel Nov 05 '13 at 15:39
5

Simple: Because you'll leak memory. And memory leaks are bad. Leaks: bad, free: good.
When calling malloc or calloc, or indeed any *alloc function, you're claiming a chunk of memory (the size of which is defined by the arguments passed to the allocating function).

Unlike stack variables, which reside in a portion of memory the program has, sort of, free reign over, the same rules don't apply to heap memory. You may need to allocate heap memory for any number of reasons: the stack isn't big enough, you need an array of pointers, but have no way of knowing how big this array will need to be at compile time, you need to share some chunk of memory (threading nightmares), a struct that requires the members to be set at various places (functions) in your program...

Some of these reasons, by their very nature, imply that the memory can't be freed as soon as pointer to that memory goes out of scope. Another pointer might still be around, in another scope, that points to the same block of memory.
There is, though, as mentioned in one of the comments, a slight drawback to this: heap memory requires not just more awareness on the programmers part, but it's also more expensive, and slower than working on the stack.
So some rules of thumb are:

  • You claimed the memory, so you take care of it... you make sure it's freed when you're done playing around with it.
  • Don't use heap memory without a valid reason. Avoiding stack overflow, for example, is a valid reason.

Anyway, Some examples:
Stack overflow:

#include <stdio.h>
int main()
{
    int foo[2000000000];//stack overflow, array is too large!
    return 0;
}

So, here we've depleted the stack, we need to allocate the memory on the heap:

#include <stdio.h>
#include <stdlib.h>
int main()
{
    int *foo= malloc(2000000000*sizeof(int));//heap is bigger
    if (foo == NULL)
    {
        fprintf(stderr, "But not big enough\n");
    }
    free(foo);//free claimed memory
    return 0;
}

Or, an example of an array, whose length depends on user input:

#include <stdio.h>
#include <stdlib.h>
int main()
{
    int *arr = NULL;//null pointer
    int arrLen;
    scanf("%d", &arrLen);
    arr = malloc(arrLen * sizeof(int));
    if (arr == NULL)
    {
        fprintf(stderr, "Not enough heap-mem for %d ints\n", arrLen);
        exit ( EXIT_FAILURE);
    }
    //do stuff
    free(arr);
    return 0;
}

And so the list goes on... Another case where malloc or calloc is useful: An array of strings, that all might vary in size. Compare:

char str_array[20][100];

In this case str_array is an array of 20 char arrays (or strings), each 100 chars long. But what if 100 chars is the maximum you'll ever need, and on average, you'll only ever use 25 chars, or less?
You're writing in C, because it's fast and your program won't use any more resources than it actually needs? Then this isn't what you actually want to be doing. More likely, you want:

char *str_array[20];
for (int i=0;i<20;++i) str_array[i] = malloc((someInt+i)*sizeof(int));

Now each element in the str_array has exactly the amount of memory I need allocated too it. That's just way more clean. However, in this case calling free(str_array) won't cut it. Another rule of thumb is: Each alloc call has to have a free call to match it, so deallocating this memory looks like this:

for (i=0;i<20;++i) free(str_array[i]);

Note:
Dynamically allocated memory isn't the only cause for mem-leaks. It has to be said. If you read a file, opening a file pointer using fopen, but failing to close that file (fclose) will cause a leak, too:

int main()
{//LEAK!!
    FILE *fp = fopen("some_file.txt", "w");
    if (fp == NULL) exit(EXIT_FAILURE);
    fwritef(fp, "%s\n", "I was written in a buggy program");
    return 0;
}

Will compile and run just fine, but it will contain a leak, that is easily plugged (and it should be plugged) by adding just one line:

int main()
{//OK
    FILE *fp = fopen("some_file.txt", "w");
    if (fp == NULL) exit(EXIT_FAILURE);
    fwritef(fp, "%s\n", "I was written in a bug-free(?) program");
    fclose(fp);
    return 0;
}

As an asside: if the scope is really long, chances are you're trying to cram too much into a single function. Even so, if you're not: you can free up claimed memory at any point, it needn't be the end of the current scope:

_Bool some_long_f()
{
    int *foo = malloc(2000000000*sizeof(int));
    if (foo == NULL) exit(EXIT_FAILURE);
    //do stuff with foo
    free(foo);
    //do more stuff
    //and some more
    //...
    //and more
    return true;
}
Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149
2

Because stack and heap, mentioned many times in the other answers, are sometimes misunderstood terms, even amongst C programmers, Here is a great conversation discussing that topic....

So why is it bad practice to not free memory on the heap but okay for memory on the stack to not be freed (until the scope ends)?

Memory on the stack, such as memory allocated to automatic variables, will be automatically freed upon exiting the scope in which they were created. whether scope means global file, or function, or within a block ( {...} ) within a function.
But memory on the heap, such as that created using malloc(), calloc(), or even fopen() allocate memory resources that will not be made available to any other purpose until you explicity free them using free(), or fclose()

To illustrate why it is bad practice to allocate memory without freeing it, consider what would happen if an application were designed to run autonomously for very long time, say that application was used in the PID loop controlling the cruise control on your car. And, in that application there was un-freed memory, and that after 3 hours of running, the memory available in the microprocessor is exhausted, causing the PID to suddenly rail. "Ah!", you say, "This will never happen!" Yes, it does. (look here). (not exactly the same problem, but you get the idea)

If that word picture doesn't do the trick, then observe what happens when you run this application (with memory leaks) on your own PC. (at least view the graphic below to see what it did on mine)

Your computer will exhibit increasingly sluggish behavior until it eventually stops working. Likely, you will be required to re-boot to restore normal behavior.
(I would not recommend running it)

#include <ansi_c.h>
char *buf=0;

int main(void)
{
    long long i;
    char text[]="a;lskdddddddd;js;'";

    buf = malloc(1000000);

    strcat(buf, "a;lskdddddddd;js;dlkag;lkjsda;gkl;sdfja;klagj;aglkjaf;d");
    i=1;    
    while(strlen(buf) < i*1000000)
    {
        strcat(buf,text); 
        if(strlen(buf) > (i*10000) -10)
        {
            i++;
            buf = realloc(buf, 10000000*i); 
        }
    }
    return 0;   
}  

Memory usage after just 30 seconds of running this memory pig:

enter image description here

Community
  • 1
  • 1
ryyker
  • 22,849
  • 3
  • 43
  • 87
  • 1
    It would be interesting to see when "memory pig" achieves the limit for a process. Sure, if it is not 64 bit. BTW: nice graphic tool – Michael Nov 05 '13 at 16:17
  • Thanks. The graphic tool is just the _Performance_ tab on Windows 7 Task Manager ( _ Start Task Manager_ ) – ryyker Nov 07 '13 at 16:00
0

I guess that has to do with scope 'ending' really often (at the end of a function) meaning if you return from that function creating a and allocating b, you will have freed in a sense the memory taken by a, and lost for the remainder of the execution memory used by b

Try calling that function a a handful of times, and you'll soon exhaust all of your memory. This never happens with stack variables (except in the case of a defectuous recursion)

Eregrith
  • 4,263
  • 18
  • 39
  • What if the whole program runs in one scope? Doesn't that mean the space is unreusable until the end of the program? Kinda like memory on the heap? – dfg Nov 05 '13 at 15:34
0

Memory for local variables automatically is reclaimed when the function is left (by resetting the frame pointer).

Axel
  • 13,939
  • 5
  • 50
  • 79
  • What if the whole program runs in one scope? Doesn't that mean the space is unreusable until the end of the program? Kinda like memory on the heap? – dfg Nov 05 '13 at 15:34
  • You can always something that doesn't work by abusing the system. Who would write such a program, and who would be the poor guy responsible for maintenance? – Axel Nov 05 '13 at 15:36
  • You can't run the program in only one scope, that would mean no function calls, only your main, only one big file ... this has so many problems to begin with – Eregrith Nov 05 '13 at 15:37
  • And this would mean you will have to declare a whole bunch of horribly named variables, and so on... just get real – Eregrith Nov 05 '13 at 15:38
  • @Eregrith Yes, you can. It obviously wouldn't by the best practice, but it would work... – dfg Nov 05 '13 at 15:38
  • It wont just be "not best practice" it would be really stupid. – Eregrith Nov 05 '13 at 15:38
  • @Eregrith Do you understand what hypothetical means? – dfg Nov 05 '13 at 15:40
  • Well ok, imagine you want to reach memory exhaustion with just stack variables and one scope. You could declare an array of arrays of arrays of size 10000 and then boom it won't be ok because the stack takes all the place. Big deal – Eregrith Nov 05 '13 at 15:40
0

The problem is that memory you allocate on the heap never gets freed until your program ends, unless you explicitly free it. That means every time you allocate more heap memory, you reduce available memory more and more, until eventually your program runs out (in theory).

Stack memory is different because it's laid-out and used in a predictable pattern, as determined by the compiler. It expands as needed for a given block, then contracts when the block ends.

Peter Bloomfield
  • 5,578
  • 26
  • 37
0

So why is it bad practice to not free memory on the heap but okay for memory on the stack to not be freed (until the scope ends)?

Imagine the following:

while ( some_condition() )
{
  int x;
  char *foo = malloc( sizeof *foo * N );

  // do something interesting with x and foo
}

Both x and foo are auto ("stack") variables. Logically speaking, a new instance for each is created and destroyed in each loop iteration1; no matter how many times this loop runs, the program will only allocate enough memory for a single instance of each.

However, each time through the loop, N bytes are allocated from the heap, and the address of those bytes is written to foo. Even though the variable foo ceases to exist at the end of the loop, that heap memory remains allocated, and now you can't free it because you've lost the reference to it. So each time the loop runs, another N bytes of heap memory is allocated. Over time, you run out of heap memory, which may cause your code to crash, or even cause a kernel panic depending on the platform. Even before then, you may see degraded performance in your code or other processes running on the same machine.

For long-running processes like Web servers, this is deadly. You always want to make sure you clean up after yourself. Stack-based variables are cleaned up for you, but you're responsible for cleaning up the heap after you're done.


1. In practice, this (usually) isn't the case; if you look at the generated machine code, you'll (usually) see the stack space allocated for x and foo at function entry. Usually, space for all local variables (regardless of their scope within the function) is allocated at once.
John Bode
  • 119,563
  • 19
  • 122
  • 198