43

Am I correct in thinking that:

char *buff[500];

... creates a stack variable, and:

char *buff = (char *)malloc(500);

... creates a heap variable?

If that's correct, when and why would you use heap variables over stack variables and vice versa. I understand the stack is faster is there anything else.

One last question, is the main function a stack frame on the stack?

Jack Harvin
  • 5,885
  • 7
  • 21
  • 21
  • 6
    to have the two allocations comparable, you probably wanted to have a version without `*` for the first, no? – Jens Gustedt Mar 10 '11 at 12:15
  • 3
    One nit: there is no such thing as a "heap variable". In your example `char *buff` is a *variable*, but the memory it points to (obtained by `malloc`) is not called a variable; it's called an object. Variables in C have a name, scope, storage duration, and possibly linkage. Each variable has an associated object which contains (the representation of) its value, but the converse is not true. – R.. GitHub STOP HELPING ICE Mar 10 '11 at 14:21

8 Answers8

65

Yes, first one creates an array of char pointers in the stack, about 500*4 bytes and second one allocates 500 chars in the heap and points a stack char ptr to them.

Allocating in the stack is easy and fast, but stack is limited, heap is slower but much bigger. Apart from that, stack allocated values are "deleted" once you leave the scope, so it is very good for small local values like primitive variables.

If you allocate too much in the stack you might run out of stack and die, main as all the functions you execute has a stack frame in the stack and all the local variables to the function are stored there, so going too deep into function calling might get you into a stackoverflow as well.

In general is a good rule of thumb to allocate anything that you use often and is bigger than a hundred bytes in the heap, and small variables and pointers in the stack.

Arkaitz Jimenez
  • 20,424
  • 9
  • 68
  • 99
  • awesome response! Thank you Arkaitz. – Jack Harvin Mar 10 '11 at 11:11
  • 3
    Also 2 point out one should be extra cautious while using memory on heap. Since the pointers are stored on the stack(and hence are local), this leads to memory management issues such as dangling pointers. So prefer using smart pointers. – letsc Mar 10 '11 at 15:16
9

Seeing that you wrote

char *buff = (char *)malloc(500);

you probably meant

char buff[500];    instead of 
char* buff[500];

in your first example (so you have a char-array, not an array of pointers to chars)

Yes, "allocation" on the stack is faster because you just increase a pointer stored in the ESP register.

You need heap-variables if you want:

1) more memory than fits in the stack (generally much earlier)

2) pass memory that was allocated by a called function to the calling function.

Bernd Elkemann
  • 22,657
  • 4
  • 36
  • 58
  • Yes sorry, forgot to add the pointer. Again another perfect answer. Daymn wish I could pick 2 best answers. – Jack Harvin Mar 10 '11 at 11:12
  • @eznme: excuse the dumb question, but... I wonder: **2) pass memory that was allocated by a called function to the calling function.** - say I was allocating a vector by simply saying: vector `someReturnedVector = myFunctionReturningVectorOfInts();` I assumed the vector created by the `myFunctionReturningVectorOfInts()` function is created on the stack and yet returning to the function it is called from, or am I horribly mislead here? – AnyOneElse Oct 09 '13 at 07:27
  • @AnyOneElse This question and these answers are about C not C++. C++ has many more rules about what is passed by value or pointer or reference or moved. I suggest you open a new question to find out for sure. – Bernd Elkemann Oct 09 '13 at 09:22
9

Your buffs are not equivalent.

The first one (char *buff[500]) is an array of 500 pointers; the 2nd one (char *buff = (char *)malloc(500)) is a pointer.

The pointer (on the stack) points to 500 bytes of memory (if the malloc call succeeded) on the heap.
The array of pointers is on the stack. Its pointers are not initialized.

pmg
  • 98,431
  • 10
  • 118
  • 189
4

Unless using C99, using the stack the size of your array must be known at compile-time. That means you cannot do:

int size = 3; // somewhere, possibly from user input
char *buff[size];

But using "the heap" (dynamic allocation), you can provide any dimensions you like. That's because the memory allocation is performed at run-time, rather than hardcoded into the executable.

Lightness Races in Orbit
  • 358,771
  • 68
  • 593
  • 989
  • 1
    On some systems (Linux, BSD) there's alloca(...) which allocates in automatic storage, having essentially the same effect like C99 variable size arrays. I write automatic, because C doesn't define the concept of stack and heap. C refers to them as automatic and allocated storage. Additional to that comes static storage (6.2.4 in the C99 standard). – datenwolf Mar 10 '11 at 11:18
  • @datenwolf: I'm glad to hear that. I am very finicky about usage of the inaccurate terms "stack" and "heap" in C++ (my preferred language), but didn't want to go into that here because I didn't know how accurate my rant would be in a C context. :) – Lightness Races in Orbit Mar 10 '11 at 11:21
  • Great that someone has pointed out possibility to use VLA (variable-length arrays) in C99, even if this term have not been used. I see that many other answers forgot about this possibility. It is useful information for those starting with C in my opinion. – rsc Mar 10 '11 at 12:23
  • VLA and alloca are both very dangerous and almost never useful (because if you use them in a way that you can ensure safety, you might as well have either used a large fixed-size buffer or `malloc` anyway). – R.. GitHub STOP HELPING ICE Mar 10 '11 at 14:19
1

The C standard contains neither the words heap nor stack. What we have here instead are two storage durations (of 4 in total): automatic and allocated:

  • char buff[500]; // note the missing * to match the malloc example
    

    within a function declares the object buff as an array of char and having automatic storage duration. The object will cease to be when the block where the object was declared, is exited.

  • char *buff = malloc(500);  // no cast necessary; this is C
    

    will declare buff as a pointer to char. malloc will reserve 500 continuous bytes and return a pointer to it. The returned 500-byte object will exist until it is explicitly freed with a call to free. The object is said to have allocated storage duration.


That's all the C standard says. It doesn't specify that the char buff[500] needs to be allocated from a "stack", or that there needs to be a stack. It doesn't specify that the malloc needs to use some "heap". On the contrary, a compiler might internally implement the char buff[500] like

{
    char *buff = malloc(500);
    free(buff);
}

Or it can deduce that the allocated memory is not used, or that it is only used once, and use a stack-based allocation instead of actually calling malloc.

In practice, most current compilers and environments will use a memory layout called stack for automatic variables, and the objects with allocated storage duration are said to come from "heap" which is a metaphor for the unorganized mess that it is compared to the orderly stack, but it is not something that has to be so.

Antti Haapala
  • 117,318
  • 21
  • 243
  • 279
1

Heap variables can be created dynamically, ie you can ask a size to your user and malloc a new variable with this size.

The size of a stack variable must be known at compile time.

Like you said, stack variable are faster allocated and accessed. So i'll recommend using them every time you know the size at compile time. Otherwise you don't have the choice, you must use malloc()

krtek
  • 25,218
  • 5
  • 53
  • 79
1

This is indeed a variable allocated on the stack:

char buff[500]; // You had a typo here?

and this is on the heap:

char *buff = (char *)malloc(500);

Why would you use one vs the other?

  • In char *buff[500], the 500 needs to be a compile-time constant. You can't use it if 500 is computed at runtime.
  • On the other hand, stack allocations are instantaneous while heap allocations take time (thus they incur a runtime performance cost).
  • Space on the stack is limited by the thread's stack size (typically 1MB before you get a stack overflow), while there's much more available on the heap.
  • If you allocate an array on the stack big enough to take up more than 2 pages of virtual memory as managed by the OS, and access the end of the array before doing anything else, there's the possibility of getting a protection fault (this depends on the OS)

Finally: every function called has a frame on the stack. The main function is no different. It isn't even any more special than the other functions in your program, since when your program starts running the first code that runs is inside the C runtime environment. After the runtime is ready to begin execution of your own code, it calls main just as you would call any other function.

Jon
  • 396,160
  • 71
  • 697
  • 768
  • You can use it if the 500 is computed at runtime, but it's dangerous, and there's no way to know what values are safe... – R.. GitHub STOP HELPING ICE Mar 10 '11 at 14:23
  • Usage of dynamic array sizes depends on compilers. I remember how confused I was to see the following code: char buff[myDynamicLength]. Visual Studio did not let me compile it but Dev++ compiled it (using GCC, I guess). But anyway, it seems to be a bad practice and should be avoided. – JustAMartin Sep 30 '13 at 18:32
0

Those two aren't equivalent. The first is an array of size 500 (on the stack) with pointers to characters. The second is a pointer to a memory chunk of 500 which can be used with the indexing operator.

char buff[500];

char *buff = (char *)malloc(sizeof(char)*500);

Stack variables should be preferred because they require no deallocation. Heap variables allow passing of data between scopes as well as dynamic allocation.

Novikov
  • 4,243
  • 2
  • 22
  • 36