In reference to the link below which explains how to find if the machine stack grows up ofr down in memory ... i want to know if the following would be the correct way to find if the machine's heap grows up or down in memory.
How would you find out if a machine’s stack grows up or down in memory? (JAVA)
my code
void findHeapDirection(int *a) {
int *b;
b = (int*)malloc(sizeof(b));
printf("\naddress of a %x",a);
printf("\naddress of b %x",&b);
if(b > a)
printf("\n>>heap grows up");
else
printf("\n>>heap grows down");
free(b);
}
and call this function like this
int *a;
a = (int*)malloc(sizeof(a));
findHeapDirection(a);
free(a);
this was the output on my machine..
address of a 5417b0
address of b 28ff14
>>heap grows up
Or is this question ambiguous as heap can never grow downwards?
You don't need a function call to test things with the heap. That's there in the linked question about the direction of the stack because the compiler might reorder variables on the stack within a single frame (or function). It will not do that for function calls, so two successive malloc() calls without a method invocation between would be as effective as your example.
However, the difference between the numbers in your example is large compared to the difference between numbers in the linked question. The heap does indeed grow in one direction, but that doesn't mean two adjacent malloc() calls will have a change in address value that implies that direction--it's more of a general trend.
The stack and the heap grow towards each other. The simplest way to find out which direction the heap grows would be to find out which direction the stack goes (which you have from the linked question) and know the heap grows in the other direction.
Related
Well, my question is as follows, I saw somewhere that a linux process allocates 8 MiB on the stack to be used, if I have a C program for example, that I only allocate two variables on the stack, it is right to say that I allocated or is it better to say that I just reused that space? Since a process allocates 8 MiB on the stack it does not depend on the size that I am going to use in my program, as long as it does not exceed my stack, that is, whichever term is appropriate, I will allocate a data on the stack or I will reuse a data that has already been allocated by a linux process?
#include <stdio.h>
void f() {
int x = 5;
printf("Value = %d End = %p\n", x, &x);
}
void g() {
int y = 10;
printf("Value = %d End = %p\n", y, &y);
}
int main(){
f();
g();
return 0;
}
See that the addresses will be the same, because I reused the size that had already been allocated, the same wouldn't happen with malloc, summarizing the term Allocated right data in the Stack isn't very correct?
Is the stack pre-allocated in a process?
On a stack-based architecture, a process will have stack space available to it from the beginning of its execution. That could be described as "pre-allocated". However, do note that in some contexts, it may be possible for a process's stack to be extended during the lifetime of the process. Perhaps that changes how you would view it?
In any case, that has little to do with whether the process of assigning storage space for automatic variables should be described as "allocation". Although it has technical implications, it is of little account linguistically that such space may be carved out of the stack, as opposed to out of some other area of memory controlled by the process. The lifetimes of such objects do obey different rules than the lifetimes of mallocated objects, but so what?
if I have a C program for example, that I only allocate two variables on the stack, it is right to say that I allocated or is it better to say that I just reused that space?
People are likely to understand you just fine either way. Although I'm sure there are some who would quibble over whether "allocate" is technically correct for automatic variables, it is nevertheless widely used for them. If you are conversing with people, as opposed to writing technical documentation to which the distinction is important, then I would not hesitate to use "allocate" to describe assigning storage space to automatic variables.
Memory allocated by malloc can be reallocated with realloc. Is there a similar function for alloca? Reallocating stack memory could be useful when you don't want memory to be allocated on the heap, and you need to allocate variable stack memory multiple times, for example in a library function, where you need dynamic memory, but don't want to allocate on the heap, because the user of the library might use a custom heap allocation strategy. It would look like this:
int main(void) {
float * some_mem = alloca(40 * sizeof(float));
// do something with this memory...
// now we need a different amount of memory, but some_mem still occupies a lot of the stack, so just reallocate it.
// is something like this possible?
some_mem = realloca(some_mem, 50 * sizeof(float));
}
The important thing is that this all happens on the stack. Q: is there a way to reallocate dynamic stack memory?
No: that wouldn't work with a stack as commonly implemented. A variable on the stack occupies a fixed range of addresses. The next variable comes immediately after it, so there's no room to grow. Consider a function like this:
void f(int x) {
int i;
float *a = alloca(40 * sizeof(float));
int k;
…
}
The stack after the function prologue looks something like this:
----------------+-----+-----+-----+-------------------+-----+---------------------
... | ret | x | i | a | k | ...
----------------+-----+-----+-----+-------------------+-----+---------------------
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
previous frames f's frame free space at the top
There's no room to grow a.
I'm showing a highly simplified example: in the real world, variables end up in registers, variables can be reordered even if they do end up on the stack, etc. But only one variable can be the last one on the stack with room to grow.
So if realloca existed, it could only be applied to the variable that's at the top of the stack. (Or else it would have to move everything else that's on top of it, but that would require updating all existing pointers to those, which is not possible in general.) This would be a very limited mechanism, so support for this feature would have a very small benefit. Supporting it would have a significant cost, because compilers are normally free to put things on the stack in the order they want: this feature would require a new mechanism to let the compiler know that one specific variable must go to the top.
It's possible that some C implementation somewhere has realloca, but it's unlikely given the cost/benefit ratio.
Of course realloca can easily be implemented if alloca does not use a stack allocation strategy. But allocating on the stack is the whole point of alloca. If you want resizable objects, you need a memory management structure with a heap interface, and that's what malloc is for.
As a practical matter, there are several possible approaches to dynamic memory management in a library.
The most common approach is to call malloc, realloc and free when you need them. That's what they're for.
In some environments, it's useful to support custom allocators. You can give the user of the library the option to pass pointers to alternative implementations of malloc, realloc and free. It's useful when you want to write a portable library that needs to be used by code that is itself fully portable. Most of the time, though, users who want to use custom allocators can do it by linking their own malloc and friends. And even that is rarely useful.
If you need code that can work in an environment without dynamic allocation (such as safety-critical environments), then you should not use alloca either. alloca is worse than malloc because it causes unpredictable stack usage and can lead to a stack overflow which won't be detected at all, or which will only be detected by a program crash. If you need a variable (or large) amount of temporary memory in a function, have the user pass a suitably-sized buffer to you.
/** [documentation of the function] …
* working_buffer must point to an array of floats of 3*n elements.
*/
void f(size_t n, float *working_buffer);
Better, if you have the code size budget, pass the array size and verify it.
/** [documentation of the function] …
* working_buffer must point to an array of floats of 3*n elements.
*/
int f(size_t n, float *working_buffer, size_t working_buffer_length)
{
if (working_buffer_length < 3 * n) return -EINVAL;
…
}
The accepted answer has correctly pointed out that usually there is not enough benefit from realloca because allocations are difficult to "grow".
Another issue I see is that these allocations have a life time till the end of the function. What happens when you pass this pointer to another function and call realloca on it there? This function would not be able to change the stack frame of a function deeper on the stack. It also cannot reallocate it in its own frame because the object would be destroyed when it returns, whereas the original object would still have to be alive.
This problem is not there for malloc/realloc because the heap has a global lifetime.
One could argue that the semantics can be defined in such way that a function can be realloced only in the function it was alloc'd in. This greatly reduces the use such a function would have.
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
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 : %d\n",c);
return;
}
printf("%p %d %p\n",&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 allocated\n");
return;
}
printf("%p %p\n",&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 (e.g. 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 (i.e. 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
I'm just curious if there is any correlation between the length of the address of a variable (pointer) on stack and heap. On many occasions I have seen that those regarding stack variables are usually longer when compared to heap. For example consider the following simple test:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i = 0;
int *j = malloc(sizeof(int)); *j = 0;
printf("&i = %p\n j = %p\n", &i, j);
free(j);
return 0;
}
output:
&i = 0x7fffe9c7fa5c
j = 0x100e010
These results are obtained in linux using gcc; could this be OS/compiler dependent?
The results depend on positions of the heap(s) and stack(s) in the address space of the program. These are determined by linker and processor architecture.
Due to ASLR, the exact numbers should be random on modern systems.
Nevertheless, heaps will usually grow upwards, and stacks downwards. Additionally, for performance and memory management reasons, both heaps and stacks will always start on page boundaries.
I believe it's because of the physical parts of the memory which we decide that they're called stack and heap. Since they start at opposite ends and grow towards the middle, it makes sense that one is lower and the other higher. It would be interesting to see what happens if you allocate 2 consecutive vars on the stack and 2 consecutive ones on the heap. This would help see which way the stack and heap grow. Actually I think for this to work you need to make a new stack frame (a new method) and allocate the second vars there, otherwise you remain in the same stack frame.
I am new to this forum and I am still an amateur in programming languages so please be kind with any of my silly mistakes :p
I am programming a recursive function which builds a kd-tree for a search process. I am using the c language on Visual Studio '08. After some seconds of processing, the program execution halts due to an error namely:
Unhandled exception at 0x77063de7 in run_FAST_corner_detection.exe:
0xC00000FD: Stack overflow
Now when the code breaks, there is a green arrow just near the instruction:
kd_node = malloc(sizeof(struct kd_node));
//this function allocates a pointer to a reserved memory of size struct kd_node.
Is this the classical problem of running out of memory?
How can I monitor the stack memory? (I know that this question has been asked repeatedly but honestly I have yet found no good method to do this).
Well, the stack overflow might be due to you calling malloc while deep in the recursion. The call to malloc pushes the return address and perhaps even parameters on the stack and this might be the thing which causes the stack to overflow. Don't do recursions in your code - try to make the code iterative (with loops instead). This is especially true for when the recursion is not bounded.
To monitor stack usage, simply take the address of any local variable (one defined within a function), and compare it against the address of a local variable in your main function (or thread entry function):
int stack_bottom;
int stack-usage () {
int top = 0;
/* Note, stack grows downward through memory, so high - low is .. */
return stack_bottom - (int)⊤
}
....
int main () {
int bottom = 0;
stack_bottom = (int)⊥
....
}
To reduce stack usage, either limit recursion, or avoid using large local variables (such as structs, arrays) and don't use alloca. You can replace large local variable with pointers to dynamically allocated heap memory (but don't forget to free it!)