memory allocation in Stack and Heap
Asked Answered
W

6

32

This may seem like a very basic question, but its been in my head so:

When we allocate a local variable, it goes into stack. Similarly dynamic allocation cause the variable to go on heap. Now, my question is, is this variable actually lie on stack or heap or we will just a reference in the stack and Heap.

For example,

Suppose I declare a variable int i. Now this i is allocated on the stack. So, when I print the address of i, this will be one of the location on stack? Same question for heap as well.

Whalebone answered 21/7, 2011 at 2:9 Comment(0)
P
91

I'm not entirely sure what you're asking, but I'll try my best to answer.

The following declares a variable i on the stack:

int i;

When I ask for an address using &i I get the actual location on the stack.

When I allocate something dynamically using malloc, there are actually TWO pieces of data being stored. The dynamic memory is allocated on the heap, and the pointer itself is allocated on the stack. So in this code:

int* j = malloc(sizeof(int));

This is allocating space on the heap for an integer. It's also allocating space on the stack for a pointer (j). The variable j's value is set to the address returned by malloc.

Pender answered 21/7, 2011 at 2:16 Comment(7)
Thanks Chris for your answer. This was the answer i was looking for. So, that is the reason why we have a problem of Programs running out of Stack but never out of HEAP, because HEAP would be limited by the memory system has.Whalebone
Actually the only reason that programs run out of stack space so quickly is because it's common practice to put very small limits on the stack space (I think 8KB is pretty common). And yes, the heap can get pretty dang big if you let it.Pender
@Samir no. Both stack and heap are limited by the amount of system memory. Programs run out of stack before they run out of heap because the stack sizes is typically orders of magnitude smaller than the heap. Programs can still run out of heap though.Elboa
@Chris: On Windows, the limit is usually 1MB, not 8kB. I assume that other systems have similar limits. Of course, this is probably very different for embedded systems.Margalo
@Rudy: I thought that on Windows the limits were compiled INTO the binary, and therefore up to the developer. I could definitely believe that 1MB is the default, 8KB seems pretty spartan if you ask me...Pender
I agree with you matt, but on a 32bit system, SP/BP will only be able to access 2GB of locations because of the pointer size and this would ensure that your stack can never grow over that size even if u do not have restriction on stack space. But on the same system, your heap can have more than 2GB of accessible location. Please correct me if i am wrong.Whalebone
@Chris: 1MB is the default on Windows (and that is hardly ever changed, IME). But you mentioned 8KB as being pretty common. Now you think it is pretty Spartan.Margalo
B
18

Hopefully the following is helpful:

void foo()
{
    // an integer stored on the stack
    int a_stack_integer; 

    // a pointer to integer data, the pointer itself is stored on the stack
    int *a_stack_pointer; 

    // make a_stack_pointer "point" to integer data that's allocated on the heap
    a_stack_pointer = (int*)malloc(10 * sizeof(int));
}

In the case of stack variables, the variable itself (the actual data) is stored on the stack.

In the case of heap allocated memory, the underlying data is always stored on the heap. A pointer to this memory/data may be stored locally on the stack.

Hope this helps.

Bevy answered 21/7, 2011 at 2:19 Comment(2)
This was helpful Darren, but can you explain to me a scearnio where the in case of heap allocated memory, pointer may not be stored on stack?Whalebone
@Samir: You may have a more complex data structure, where the heap allocated data contains pointers to other segments of heap allocated data. The conventional implementation of a linked-list would be an example of this, where each "node" in the list contains a pointer to the next "node" and so onBevy
J
7

The pointer variable itself would reside on the stack. The memory that the pointer points to would reside on the heap.

int *i = malloc(sizeof(int));

i would reside on the stack, the actual memory that i points to *i would be on the heap.

Jews answered 21/7, 2011 at 2:17 Comment(0)
G
3

I agree with Chris. Just another way to explain that. Consider the following code:

int* j = malloc(sizeof(int));
free(j);

Even after using free(j) which should deallocate the memory from the heap, the pointer still exists and we need to explicitly make it NULL. This definitely suggests that there is also a stack counterpart of the pointer otherwise it should have been inexistent after the free command. This stack variable is the one pointing to the address on the heap where the memory was dynamically allocated using malloc.

Goodin answered 3/6, 2013 at 10:8 Comment(2)
Don't think this is a good example. Explicitly needing it set the pointer to NULL here doesn't have to do with the type so much as it has to do with the compiler and library implementation of free. I could make my own implementation of free that took a **int and you pass in &j, this could both free the memory AND set the pointer to null, yet one is still on the heap and the other on the stack.Osmious
the 'should' deallocate is a bit misleading too, it absolutely does deallocate the memory from the heap. The stack variable on the other hand is deallocated for us when it's context is no longer valid. That's what people coming to this answer need to really consider... for variables on the stack the memory is allocated at compile time and it's location is known which is normally at a fixed address just ahead of the function and its parameters on the stack while variables on the heap are allocated at runtime and are located in a separate block of memory dedicated specifically for 'heap' memory.Osmious
J
2

Mr. Eberle's answer is 100% correct, but since Google shows this as the first answer when searching for malloc heap or stack, I have to add that malloc() allocates data on the heap 'most' of the time. If the allocated data was larger than MMAP_THRESHOLD which is usually 128kb on 32-bit systems, malloc() will not use the heap and instead allocates the data in an Anonymous Memory Segment located usually below the stack, growing in the direction of low memory.

This is the same region that dynamically loaded libraries are located (libc.so, etc.). Here's the relevant passage from man malloc:

Normally, malloc() allocates memory from the heap, and adjusts the size of the heap as required, using sbrk(2). When allocating blocks of memory larger than MMAP_THRESHOLD bytes, the glibc malloc() implementation allocates the memory as a private anonymous mapping using mmap(2). MMAP_THRESHOLD is 128 kB by default, but is adjustable using mallopt(3). Prior to Linux 4.7 allocations performed using mmap(2) were unaffected by the RLIMIT_DATA resource limit; since Linux 4.7, this limit is also enforced for allocations performed using mmap(2).

As a practical example, feel free to check the following post. It basically allocates 300kb with malloc() and then runs pmap <PID> to show the relevant memory segment.

Janeejaneen answered 25/8, 2018 at 9:23 Comment(1)
Pretty sure MMAP_THRESHOLD isn't part of ANSI/ISO C or any POSIX standard. Still interesting, but not an inherent truth of all C implementations. Looks like that's true for glibc and musl though.Horvitz
C
0

stack or heap are not separate memory, they are memory segments that a running program is allocated by the system, just different ways of organizing data in memory.

So when you get &i, it is a memory address, simple as that.

Christianachristiane answered 21/7, 2011 at 2:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.