local variable memory and malloced memory location

I was playing up with malloced memory and local variables to see how stack and Heap grows. From my understanding heap grows upwards and the stack grows downwards. All the memory allocated using malloc is allocated in the heap and local variables are allocated on the stack in a function.

In following program :

#include <stdio.h>
#include <stdlib.h>
#define SIZE 999999999
void tot(){
    static int c =0;
    int k;
    c++;
    int *pp = malloc(sizeof(int) * SIZE);
    if(pp==NULL){
        fprintf(stderr,"NO memory allocated after call : %dn",c);
        return;
    }
        printf("%p %d %pn",&k,c,pp);
        tot();
}

int main(int argc, char *argv[]){
    int k;
    int *pp = malloc(sizeof(int) * 99999);
    if(pp ==NULL){
        fprintf(stderr,"No memory allocatedn");
        return;
    }
        printf("%p %pn",&k,pp);
        tot();
        return 0;
}

I have created one local variable in the function tot() which will be 4 bytes and one pointer variable of type int* which will increase the total stack size for each call to slightly greater than 4 bytes. Also I have allocated some memory using malloc and assigned the allocated memory to local pointer variable. Since this malloced memory is allocated on the heap, the stack size should still be just over 4 bytes but according to my observation in the above program, the stack size is increased by a large amount. After some maths on that large amount I found out that the stack frame is including the malloced memory created in each function call.

Though removing the line

int *pp = (int*)malloc(sizeof(int) * SIZE);

which is responsible for allocating this large memory in each function call reduces the stack frame size back to ~4 bytes which is perfectly fine.

Stack frame is growing downwards in both situations though.

Why I am getting such output. Is my belief that dynamic memory is allocated on the heap is wrong. Why malloced memory is increasing the size of the stack frame ?

EDIT : I also tried accessing the allocated memory in one stack frame in other stack frame by passing the pointer to memory allocated in one stack frame to the other function call (another stack frame) so that the memory allocated in one frame can be used in other call just to verify if the compiler is not internally converting the malloc to alloca (which could have been the reason for large stack frames) but that didn't make any difference. The results are still same.


Many Linux systems have ASLR so the result of malloc might not be reproducible from one execution to the next; you can disable ASLR thru /proc/sys/kernel/randomize_va_space .

Actually, recent malloc implementations are using more the mmap(2) syscall than the sbrk or brk one. So the heap is actually made of several non-contiguous virtual memory segments. Usually, later calls to free mark the freed region as reusable by malloc (but don't necessarily munumap(2) it).

You can have a look at the address space of some process of pid 1234 by looking into /proc/1234/maps . Read proc(5) man page (and try cat /proc/self/maps which shows the address space of the process running that cat ).

And you tot function being tail recursive, most GCC compilers would optimize it as a loop.... (if you are compiling with gcc -O1 or more). However, stack frames are usually required to be aligned (eg to 16 bytes) and contain also the previous frame pointer, some space to spill registers, etc...


C is a low-level language, but it still defines things loosely enough that specific details can vary between platforms. For instance, the compiler is free to allocate varying amounts of stack space as it sees fit (typically "extra" space), so long as the results of the running program are not altered.

This may be done in the name of performance [1] or to support certain calling conventions. So even though an int may only need for bytes of space, the compiler may allocate 16 bytes on the stack to preserve a favorable memory alignment.

If the "large" increases in stack size are small compared to SIZE, then the difference is probably just due to padding of this sort. (Note that there is also more data on the stack than just the local variables - the return address of the calling function will usually be stored there, as well as the contents of any registers the compiler decided should be stored from the caller.)

If it actually looks like malloc is allocating to the stack (ie the stack is increasing in jumps of SIZE), that's surprising, but probably still "correct" on behalf of the compiler. By definition malloc allocates memory; there is no guarantee that this is allocated from the heap, although that is certainly the normal implementation. Since the results of malloc are never accessed outside of the stack frame in which it's invoked, the compiler could in principle optimize this to an alloca call; but, again, I'd be very surprised to see that.

[1] Example: http://software.intel.com/en-us/articles/data-alignment-when-migrating-to-64-bit-intel-architecture

链接地址: http://www.djcxy.com/p/82520.html

上一篇: 这是明确的堆还是堆栈动态?

下一篇: 局部变量内存和malloced内存位置