I am trying to estimate the span of my program stack range. My strategy was to assume that since the stack grows downwards, I can create a local variable to the current stack frame and then use its address as a reference.
int main()
{
//Now we are in the main frame.
//Define a local variable which would be lying in the top of the stack
char a;
//Now define another variable
int b; //address should be lower assuming stack grows downwards
//Now estimate the stack size by rlimit
struct rlimit stack_size;
getrlimit(RLIMIT_STACK,&stack_size);
//A crude estimate would be stack goes from &a to &a - stack_size.rlim_cur
printf("%p \n",&a);
printf("%p \n",&b);
printf("stack spans from %u to %u",&a,&a - stack_size.rlim_cur);
return 0;
}
Interestingly when I use the gdb to debug the values address of a and b, address of b has a higher value than a. Also the stack pointer remains always in the same place in .
0xbfca65f4
0xbfca660f
Stack spans from 0xbfca65f4 to 0xbbca65f4.
ebx 0xb7faeff4 -1208291340
esp 0xbffff670 0xbffff670
Can anybody hep me understand where I am going wrong?
Thanks in advance!
This approach mostly works; your mistake is just examining both a and b in the same call frame. There's no reason for the compiler to order automatic variables the way you expect on the stack; it's likely to choose their order for data locality or alignment purposes.
If you compare the address of one automatic object in main and another in a separate call frame (make sure it's not one that might get inlined into main!) then you should get results closer to what you expect.
Related
#include<stdio.h>
int main()
{
int a,b;
float e;
char f;
printf("int &a = %u\n",&a);
printf("int &b = %u\n",&b);
printf("float &e = %u\n",&e);
printf("char &f = %u\n",&f);
}
The Output is
int &a = 2293324
int &b = 2293320
float &e = 2293316
char &f = 2293315
But when i use this code and replace the printf for float--
#include<stdio.h>
int main()
{
int a,b;
float e;
char f;
printf("int &a = %u\n",&a);
printf("int &b = %u\n",&b);
printf("char &f = %u\n",&f);
}
Then the Output is
int &a = 2293324
int &b = 2293320
char &f = 2293319
here address is not provided to float, but it is declared on top.
My questions are
Is memory not allocated to variables not used in program?
Why addresses allocated in decreasing order. ex- it's going from 2293324 to 2293320?
1) Is memory not allocated to variables not used in program?
Yes that can happen, the compiler is allowed to optimize it out.
2) Why addresses allocated in decreasing order. ex- it's going from 2293324 to 2293320?
That is usual for most local storage implementations, that they use the CPU supported stack pointer going from stack top to stack bottom. All those local variables will be allocated at the stack most probably.
1) Is memory not allocated to variables not used in program?
It's an allowed optimization; if an unused variable doesn't affect the program's observable behavior, a compiler may just discard it completely. Note that most modern compilers will warn you about unused variables (so you can either remove them from the code or do something with them).
2) Why addresses allocated in decreasing order. ex- it's going from 2293324 to 2293320?
The compiler is not required to allocate storage for separate objects in any particular order, so don't assume that your variables will be allocated in the order they were declared. Also, remember that on x86 and some other systems, the stack grows "downwards" towards decreasing addresses. Remember the top of any stack is simply the location where something was most recently pushed - it has nothing to do with relative address values.
While not specifically required by the standard, local variables are universally located on the program stack.
When you enter a function, one of the first thing done is to decrement the stack pointer to provide space for the local variables.
SUBL #SOMETHING, SP
Where SOMETHING is the amount of space required and SP is the stack pointer register.. In your first example, SOMETHING is probably 13. Then the address of:
f is 0(SP)
e is 1(sp)
b is 5(sp)
a is 9(sp)
I am assuming your compiler did not align the stack pointer. Often they do giving something more like:
f is 3(SP)
e is 4(sp)
b is 8(sp)
a is 12(sp)
And SOMETHING would be rounded up to 16 on a 32-bit system.
You might want to generate an assembly listing using your compiler to see what is going on underneath.
Is memory not allocated to variables not used in program?
Note that for local variable memory is not really allocated. A variable is temporarily bound to a location on the program stack (stack is not required by the standard but is how it is done in most cases). That is why the variable's initial value is undefined. It could have been bound to something else previously.
The compiler does not need to reserve space for variables that are not used. They can be optimized away. Usually, there are compiler settings to instruct not to do this for debugging.
Why addresses allocated in decreasing order. ex- it's going from 2293324 to 2293320?
Program stacks generally grow downward. Starting ye olde days, the program would be at the bottom of the address space, the heap above that and the stack at the opposite end.
The heap would grow towards higher addresses. The stack would grow towards the heap (lower addresses).
While the address spaces can be more complicated than that these days, the downward growth of stacks has stayed.
There is no particular requirement that the compiler map the variables to the stack in descending order but there's a 50/50 chance it will do it that way.
I disassembled a small program that asks the user for their name then outputs "Hello + [user's_name]"
This is the disassembled output:
Main function:
Say hello function:
I noticed that for the main() function, the ESP register is decremented by Ox10 and for the say_hello() function, the ESP register is decremented by Ox20. Why is this the case?
FYI: My processor is an 1.4 GHz Intel Core i5 and I'm running OSX
Original C code:
void say_hello (void);
int main (){
printf("Enter your name\n");
say_hello();
return 0;
}
void say_hello (void) {
char name[5];
gets(name); //this is a unsafe function to use. Results in stack overflow
printf("Hello %s\n", name);
}
It allocates space on the stack for local variables. First BP it set to the current value of SP, then SP is decremented to make room for the local variables used by the function. As you can see, later [ss:rbp+???] is used to access parts of memory of this reserved space.
This is basically the same as PUSHing some dummy value a repeated number of times onto the stack.
Before the function leaves, it is crucial that the exact amount is added back to SP, otherwise a wrong return address will be used by the RET instruction, and the program will most likely crash.
The stack is "implemented" by means of the stack pointer, which points into the stack segment. Every time something is pushed on the stack (by means of pushl, call, or a similar stack opcode), it is written to the address the stack pointer points to, and the stack pointer decremented (stack is growing downwards, i.e. smaller addresses). When you pop something off the stack (popl, ret), the stack pointer is incremented and the value read off the stack.
For different function calls, we reserve space for local variables in the stack, so we decrement it and get the space. This is usually done using prologue and epilogue.
Prologue
A function prologue typically does the following actions if the architecture has a base pointer (also known as frame pointer) and a stack pointer (the following actions may not be applicable to those architectures that are missing a base pointer or stack pointer) :
Pushes the old base pointer onto the stack, such that it can be restored later (by getting the new base pointer value which is set in the next step and is always pointed to this location).
Assigns the value of stack pointer (which is pointed to the saved base pointer and the top of the old stack frame) into base pointer such that a new stack frame will be created on top of the old stack frame (i.e. the top of the old stack frame will become the base of the new stack frame).
Moves the stack pointer further by decreasing or increasing its value, depending on whether the stack grows down or up. On x86, the stack pointer is decreased to make room for variables (i.e. the function's local variables).
Epilogue
Function epilogue reverses the actions of the function prologue and returns control to the calling function. It typically does the following actions (this procedure may differ from one architecture to another):
Replaces the stack pointer with the current base (or frame) pointer, so the stack pointer is restored to its value before the prologue
Pops the base pointer off the stack, so it is restored to its value before the prologue
Returns to the calling function, by popping the previous frame's program counter off the stack and jumping to it
As far as I rememeber, such decrements are mostly used to "reserve" place on stack or to guarantee even memory alignment.
What does it mean to align the stack?
The stack frame of a caller function can be easily obtained via __builtin_frame_address(1), but what about the stack frame size?
Is there a function that will let me know how big is the stack frame of the caller function?
My first reaction would have been, why would anybody want this? It should be considered bad practice for a C function to dynamically determine the size of the stack frame. The whole point of cdecl (the classic C calling convention) is that the function itself (the 'callee') has no knowledge of the size of the stack frame. Any diversion from that philosophy may cause your code to break when switching over to a different platform, a different address size (e.g. from 32-bit to 64-bit), a different compiler or even different compiler settings (in particular optimizations).
On the other hand, since gcc already offers this function __builtin_frame_address, it will be interesting to see how much information can be derived from there.
From the documentation:
The frame address is normally the address of the first word pushed on to the stack by the function.
On x86, a function typically starts with:
push ebp ; bp for 16-bit, ebp for 32-bit, rbp for 64-bit
In other words, __builtin_frame_address returns the base pointer of the caller's stack frame.
Unfortunately, the base pointer says little or nothing about where any stack frame starts or ends;
the base pointer points to a location that is somewhere in the middle of the stack frame (between the parameters and the local variables).
If you are only interested in the part of the stack frame that holds the local variables, then the function itself has all the knowledge. The size of that part is the difference between the stack pointer and the base pointer.
register char * const basepointer asm("ebp");
register char * const stackpointer asm("esp");
size_localvars = basepointer - stackpointer;
Please keep in mind that gcc seems to allocate space on the stack right from the beginning that is used to hold parameters for other functions called from inside the callee. Strictly speaking, that space belongs to the stack frames of those other functions, but the boundary is unclear. Whether this is a problem, depends on your purpose; what you are going to do with the calculated stack frame size?
As for the other part (the parameters), that depends. If your function has a fixed number of parameters, then you could simply measure the size of the (formal) parameters. It does not guarantee that the caller actually pushed the same amount of parameters on the stack, but assuming the caller compiled without warnings against callee's prototype, it should be OK.
void callee(int a, int b, int c, int d)
{
size_params = sizeof d + (char *)&d - (char *)&a;
}
You can combine the two techniques to get the full stackframe (including return address and saved base pointer):
register char * const stackpointer asm("esp");
void callee(int a, int b, int c, int d)
{
total_size = sizeof d + (char *)&d - stackpointer;
}
If however, your function has a variable number of parameter (an 'ellipsis', like printf has), then the size of the parameters is known only to the caller. Unless the callee has a way to derive the size and number of parameters (in case of a printf-style function, by analyzing the format string), you would have to let the caller pass that information on to the callee.
EDIT:
Please note, this only works to let a function measure his own stack frame. A callee cannot calculate his caller's stack frame size; callee will have to ask caller for that information.
However, callee can make an educated guess about the size of caller's local variables. This block starts where callee's parameters end (sizeof d + (char *)&d), and ends at caller's base pointer (__builtin_frame_address(1)). The start address may be slightly inaccurate due to address alignment imposed by the compiler; the calculated size may include a piece of unused stack space.
void callee(int a, int b, int c, int d)
{
size_localvars_of_caller = __builtin_frame_address(1) - sizeof d - (char *)&d;
}
Okay I know that main()'s automatic local variables are stored in the stack and also any function automatic local variables too, but when I have tried the following code on gcc version 4.6.3:
#include <stdio.h>
int main(int argc, char *argv[]) {
int var1;
int var2;
int var3;
int var4;
printf("%p\n%p\n%p\n%p\n",&var1,&var2,&var3,&var4);
}
the results are :
0xbfca41e0
0xbfca41e4
0xbfca41e8
0xbfca41ec
according to the results var4 on the top of the stack and var1 on the bottom of the stack and the stack pointer now pointing on the address below var1 address....but why var4 on the
top of the stack and var1 on the bottom...its declared after var1 so I think logically that var1 should be on the top of the stack and any variable declared after var1 should be below
it in memory...so in my example like this:
>>var1 at 0xbfca41ec
>>var2 at 0xbfca41e8
>>var3 at 0xbfca41e4
>>var4 at 0xbfca41e0
>>and stack pointer pointing here
..
..
EDIT 1:
After reading the comment by #AusCBloke I’ve tried the following code :
#include <stdio.h>
void fun(){
int var1;
int var2;
printf("inside the function\n");
printf("%p\n%p\n",&var1,&var2);
}
int main(int argc, char *argv[]) {
int var1;
int var2;
int var3;
int var4;
printf("inside the main\n");
printf("%p\n%p\n%p\n%p\n",&var1,&var2,&var3,&var4);
fun();
return 0;
}
And the results :
inside the main
0xbfe82d60
0xbfe82d64
0xbfe82d68
0xbfe82d6c
inside the function
0xbfe82d28
0xbfe82d2c
so the variables inside fun() stack frame are below the variables inside main() stack frame and that’s true according to the nature of the stack ,..but inside the same stack frame its not necessary to be ordered from top to the bottom.
thanks #AusCBloke..... your comment helped me a lot
There is no requirement for these variables to be allocated in the order in which they were declared. They can be moved around by the compiler, or even optimized out entirely. If you need the relative addresses to stay the same, use a struct.
Objects with automatic storage duration are typically stored on the stack, but the language standard doesn't require it. In fact, the standard (the link is to the latest pre-release C11 draft)
doesn't even mention the word "stack".
The word "stack", unfortunately, is ambiguous.
In the most abstract sense, a stack is a data structure in which the most recently added items are removed first (last-in first-out, or LIFO). The requirements regarding the lifetime of objects with automatic storage duration (i.e., objects defined within a function with no static keyword) imply some kind of stack-like allocation.
The word "stack" is also commonly used to refer to a contiguous region of memory, typically controlled by a "stack pointer" pointing to the top-most element. The stack grows by moving the stack pointer away from the base, and shrinks by moving it toward the base. (It can grow in either direction, toward higher or lower memory addresses.) Most C compilers use this kind of contiguous stack to implement automatic objects -- but not all do. There have been C compilers for IBM mainframe systems which allocate storage for function calls from a heap-like structure, and the addresses for nested calls need not be uniformly in either increasing or decreasing order.
This is an unusual implementation, and there are very good reasons that this approach is not commonly used (a contiguous stack is simpler, more efficient, and is typically supported by the CPU). But the C standard is carefully written to avoid requiring a specific scheme, and C code that's carefully written to be portable will work correctly regardless of which method a compiler chooses. You don't need to know. All you really need to know about the address of var1 is that it's &var1. If you write if (&var1 < &var2) { ... }, then you're probably doing something wrong (that expression's behavior is undefined, BTW).
That's the standard C answer. I see that your question is tagged gcc. As far as I know, all versions of gcc use a contiguous stack. But even so, there's rarely any benefit in taking advantage of this.
On many (most) modern platform stack grows from higher addresses in memory to lower addresses. I..e. when you start your program, the stack pointer is immediately put to some address in memory, which is determined by the maximum stack size in your program. Once things get pushed into stack, the stack pointer actually moves down.
I could be wrong but stacks start in lower memory addresses and are then added to. So it is correct for var4 to be on top. It is a stack after all!
edit: the assembly code behind it has the stack pointer at the bottom of the memory stack and whenever data is added, the stackpointer is incremented so that the next variable falls ontop.
I'm 99.9999% sure that the answer is Yes. Also, the stack grows downwards on Intel architecture machines, not upwards. The lower area becomes the virtual "top" of the stack (it's upside-down, so to speak).
So technically, the variables are in the correct order in stack memory.
EDIT: This is probably still compiler-specific, though.
If the program counter points to the address of the next instruction to be executed, what do frame pointers do?
It's like a more stable version of the stack pointer
Storage for some local variables and parameters are generally allocated in stack frames that are automatically freed simply by popping the stack pointer back to its original level after a function call.
However, the stack pointer is frequently being adjusted in order to push arguments on to the stack for new call levels and at least once on entry to a method in order to allocate its own local variables. There are other more obscure reasons to adjust the stack pointer.
All of this adjusting complicates the use of offsets to get to the parameters, locals, and in some languages, intermediate lexical scopes. It is perhaps not too hard for the compiler to keep track but if the program is being debugged, then a debugger (human or program) must also keep track of the changing offset.
It is simpler, if technically an unnecessary overhead, to just allocate a register to point to the current frame. On x86 this is %ebp. On entry to a function it may have a fixed relationship to the stack pointer.
Besides debugging, this simplifies exception management and may even pay for itself by eliminating or optimizing some adjustments to the stack pointer.
You mentioned the program counter, so it's worth noting that generally the frame pointer is an entirely software construct, and not something that the hardware implements except to the extent that virtually every machine can do a register + offset addressing mode. Some machines like x86 do provide some hardware support in the form of addressing modes and macro instructions for creating and restoring frames. However, sometimes it is found that the core instructions are faster and the macro ops end up deprecated.
This isn't really a C question since it's totally dependent on the compiler.
However stack frames are a useful way to think about the current function and it's parent function. Typically a frame pointer points to a specific location on the stack (for the given stack depth) from which you can locate parameters that were passed in as well as local variables.
Here's an example, let's say you call a function which takes one argument and returns the sum of all numbers between 1 and that argument. The C code would be something like:
unsigned int x = sumOf (7);
: :
unsigned int sumOf (unsigned int n) {
unsigned int total = 0;
while (n > 0) {
total += n;
n--;
}
return total;
}
In order to call this function, the caller will push 7 onto the stack then call the subroutine. The function itself sets up the frame pointer and allocates space for local variables, so you may see the code:
mov r1,7 ; fixed value
push r1 ; push it for subroutine
call sumOf ; then call
retLoc: mov [x],r1 ; move return value to variable
: :
sumOf: mov fp,sp ; Set frame pointer to known location
sub sp,4 ; Allocate space for total.
: :
At that point (following the sub sp,4), you have the following stack area:
+--------+
| n(7) |
+--------+
| retLoc |
+--------+
fp -> | total |
+--------+
sp -> | |
+--------+
and you can see that you can find passed-in parameters by using addresses 'above' the frame pointer and local variables 'below' the frame pointer.
The function can access the passed in value (7) by using [fp+8], the contents of memory at fp+8 (each of those cells is four bytes in this example). It can also access its own local variable (total) with [fp-0], the contents of memory at fp-0. I've used the fp-0 nomenclature even though subtracting zero has no effect since other locals will have corresponding lower addresses like fp-4, fp-8 and so on.
As you move up and down the stack, the frame pointer also moves and it's typical that the previous frame pointer is pushed onto the stack before calling a function, to give easy recovery when leaving that function. But, whereas the stack pointer may move wildly while within a function, the frame pointer typically stays constant so you can always find your relevant variables.
Good discussion here, with examples and all.
In short: the FP points to a fixed spot within the function's frame on the stack (and does not change during function execution), so all passed-arguments and the function's local ("auto") variables can be accessed by offsets from the FP (while the SP can change during a function's execution, and the PC definitely does;-).
Usually the return address (but sometimes just past last argument, for example). The point is that the frame pointer is fixed during the life of a method while the stack pointer could move during execution.
This is very implementation dependent (and more a machine concept, not really a language concept).
Lifted from a comment you provided to another answer:
Woh... Stack Pointer?... is that synonymous to Program Counter?
Read about the call stack. Basically the call stack stores data local to a current method (local variables, parameters to the method and return address to the caller). The stack pointer points to the top of that structure which is where new space is allocated (by moving the stack pointer "higher").
The frame pointer points to an area of memory in the current frame (current local function), typically it points to the return address of the current local function.
Since no one has responded to this yet I'll give it a try. A frame pointer (if memory serves) is part of the stack along with the stack pointer. The stack is comprised of stack frames (sometimes called activation records). The stack pointer points to the top of the stack while the frame pointer typically points to some fixed point in a frame structure, such as the location of the return address. Theres a more detailed description along with a picture on wikipedia.
link text