How does the computer saves each changed 'i' value in the memory and prints them out?
How many bytes are being used in this code? 24 bytes (i = 5, 4, 3, 2, 1, 0) or only 4 bytes?
Following code prints: 1, 2, 3, 4, 5.
#include <stdio.h>
void test(int i)
{
if (i == 0) return;
test(i - 1);
printf("%d\n", i);
}
int main(void)
{
test(5);
return 0;
}
The 'stack' on modern CPU architectures is a region of memory (separate for each thread) that stores, among other things, the return address when a function call is made, function call parameters, non-static local variables (typically in that order, but not always).
Every time any function is called in C (and most modern languages), the return address (the address to jump to once the function about to be called finishes execution) is pushed onto the stack, and the stack pointer is incremented by the size of an address (assuming the stack grows up), then each function parameter is pushed onto the stack, and the stack pointer is again incremented by the size of each parameter. As each function local variable is allocated space, the stack pointer is incremented by the size of that variable as it is pushed onto the stack. When the function returns, the stack pointer is 'unwound' by the value of the size of each variable that was pushed onto the stack, as they are popped off of the stack. Next the function call parameters are popped from the stack, and again, the stack pointer is decremented by the size of each parameter. Finally, the function jumps to the return address that was originally pushed to the stack when the function was called, and it is popped, and the stack pointer is decremented by the size of an address. We are now ready to execute whatever code comes after the function call, and the stack pointer is right back where it was before the function call.
In the case of recursive function calls, the return address, function call parameters, and function local variables are pushed onto the stack for each nested function call, but are not popped from the stack until the final recursive function call returns. They are popped off the stack in the opposite order they were pushed onto the stack (as stacks are by nature Last In First Out, LIFO, data structures).
Assuming this is executing on a 32bit CPU, and an 'int' is 4 bytes, then the return address for each recursive function call, plus the one function parameter would get pushed onto the stack. At the greatest stack utilization, immediately before test(0) returns, we would have 6x recursive calls (for 5,4,3,2,1,0), and a 32 bit (4 byte) return address, plus a 4 byte parameter for each call, so 6 * (4 + 4) = 48 bytes.
Each instance of test gets its own instance of i. When you call a function, the current execution environment of the current function is stored and the context is set up for the new function. When that new function returns, the context of the calling function is restored.
Related
Sorry my C is a bit rusty.
I would like to get the return address as an exercise using only the address of the stack pointer. I know I can directly get the return address using the __builtin_return_address function but I want to do it manually with the stack pointer.
Right now I just have the address of the pointer to the return address, but I would like to get the actual address.
void a() {
void *sp = __builtin_frame_address(0);
printf("%p\n", (*(&sp) + 0x8));
}
int main() {
a();
}
From the GNU documentation for this extension:
6.51 Getting the Return or Frame Address of a Function
These functions may be used to get information about the callers of a function.
Built-in Function: void * __builtin_return_address (unsigned int level)
This function returns the return address of the current function, or of one of its callers. The level argument is number of frames to scan up the call stack. A value of 0 yields the return address of the current function, a value of 1 yields the return address of the caller of the current function, and so forth. When inlining the expected behavior is that the function returns the address of the function that is returned to. To work around this behavior use the noinline function attribute.
The level argument must be a constant integer.
On some machines it may be impossible to determine the return address of any function other than the current one; in such cases, or when the top of the stack has been reached, this function returns an unspecified value. In addition, __builtin_frame_address may be used to determine if the top of the stack has been reached.
Additional post-processing of the returned value may be needed, see __builtin_extract_return_addr.
The stored representation of the return address in memory may be different from the address returned by __builtin_return_address. For example, on AArch64 the stored address may be mangled with return address signing whereas the address returned by __builtin_return_address is not.
Calling this function with a nonzero argument can have unpredictable effects, including crashing the calling program. As a result, calls that are considered unsafe are diagnosed when the -Wframe-address option is in effect. Such calls should only be made in debugging situations.
On targets where code addresses are representable as void *,
void *addr = __builtin_extract_return_addr(__builtin_return_address(0));
gives the code address where the current function would return. For example, such an address may be used with dladdr or other interfaces that work with code addresses.
Built-in Function: void * __builtin_extract_return_addr(void *addr)
The address as returned by __builtin_return_address may have to be fed through this function to get the actual encoded address. For example, on the 31-bit S/390 platform the highest bit has to be masked out, or on SPARC platforms an offset has to be added for the true next instruction to be executed.
If no fixup is needed, this function simply passes through addr.
Built-in Function: void * __builtin_frob_return_addr(void *addr)
This function does the reverse of __builtin_extract_return_addr.
Built-in Function: void * __builtin_frame_address(unsigned int level)
This function is similar to __builtin_return_address, but it returns the address of the function frame rather than the return address of the function. Calling __builtin_frame_address with a value of 0 yields the frame address of the current function, a value of 1 yields the frame address of the caller of the current function, and so forth.
The frame is the area on the stack that holds local variables and saved registers. The frame address is normally the address of the first word pushed on to the stack by the function. However, the exact definition depends upon the processor and the calling convention. If the processor has a dedicated frame pointer register, and the function has a frame, then __builtin_frame_address returns the value of the frame pointer register.
On some machines it may be impossible to determine the frame address of any function other than the current one; in such cases, or when the top of the stack has been reached, this function returns 0 if the first frame pointer is properly initialized by the startup code.
Calling this function with a nonzero argument can have unpredictable effects, including crashing the calling program. As a result, calls that are considered unsafe are diagnosed when the -Wframe-address option is in effect. Such calls should only be made in debugging situations.
Here is the modified code:
#include <stdio.h>
void a() {
printf("return address: %p\n", __builtin_extract_return_addr(__builtin_return_address(0)));
}
int main() {
a();
return 0;
}
Getting the return address from the frame address is not always possible and is very system specific, it also depends on the function calling convention. The compiler takes these factors into consideration when compiling the builtin __builtin_return_address, it is quite tricky to try and do it by hand from the value of __builtin_frame_address.
If your goal is to construct an introspection system, you may have to store the frame and the return addresses separately. You will need to parse debugging information to try and make sense of the data accessible through these pointers.
I just tried this as an experiment to see what values are held in d at each call.
I used gcc on an x86-64 machine.
Is there any reason why the old value of d persists after the function returns? From what I understand the call stack frame is popped off once the function returns each time, correct?
#include<stdio.h>
void fun(char ch){
char d;
printf("-- %c\n", d);
d = ch;
}
int main(){
fun('a');
fun('b');
fun('c');
return 0;
}
OUTPUT:
--
-- a
-- b
When you return from a function, the memory that was part of the stack frame of the function typically won't be zero'ed out explicitly, as that would just take up unnecessary cycles. So the memory won't be overwritten until it needs to be.
In your main function you call fun multiple times with no other statements in between. That means that nothing in main touches the memory that was used by a prior invocation of fun before calling it again. As a result, the stack frame of the second call happens to coincide with the stack frame of the first call. And because uninitialized local variables don't get a default value, d takes on whatever value happens to be in that memory location, namely what d contained when the last call to the function returned.
If you added a call to another function such as printf in between each call to fun, then that other function call would write its own stack frame on top of the stack frame of the last call to fun so you would see different results in that case.
I was reading this article and saw this: "This article assumes that you already know and understand at least basically how the memory
map in GNU/Linux system works, and specially the difference between memory statically
allocated in the stack and memory dynamically allocated in the heap."
This confused me because I thought that stack and heap are dynamically allocated, meaning only allocated if necessary, and global variables and variables declared as "static" inside of a function are statically allocated, meaning always allocated.
For example, if I have
void f() {
int x = 1;
...
}
the value 1 only gets put on the stack and the stack pointer only gets incremented if the function f() gets called. Likewise, if I have
void f() {
int x = malloc(1 * sizeof(int));
...
}
that heap memory only gets allocated if f() is called. However, if I have "int x = 1;" in the global section of the program or "static int x = 1;" within a function body, any time I run this program, that memory will be allocated in the data section with the value 1.
Am I wrong about any of this?
The stack itself is statically allocated. Variables allocated in the stack come and go, as control flow enters and leaves their scope.
Static variables are initialized only once, even if the initialization statement is inside of a function body.
Check the wikipedia example:
#include <stdio.h>
void func() {
static int x = 0;
/* x is initialized only once across five calls of func() and
the variable will get incremented five
times after these calls. The final value of x will be 5. */
x++;
printf("%d\n", x); // outputs the value of x
}
int main() { //int argc, char *argv[] inside the main is optional in the particular program
func(); // prints 1
func(); // prints 2
func(); // prints 3
func(); // prints 4
func(); // prints 5
return 0;
}
The stack is basically a large statically allocated array with a movable pointer that starts at the beginning of it. When you call a function (starting w/ main), the pointer moves (creates a stack frame) and the space in the stack frame is sliced up and given to local variables (how many local variables you have determines how big your function's stack frame will be). So local variables are kind of dynamic (they only emerge once you enter the function), but the stack is of a static size. If you allocate a super large structure on it or use too much recursion, you'll go past the end and the OS will take you down—a phenomenon known as stackoverflow.
(
The icon actually illustrates this. The gray container at the bottom represents the static array that the stack is. The orange rectangles are frames created by function calls. As in a proper stack overflow, the frames overflow the container and boom -- you're program is dead. The fact that the frames go up illustrates another, rather special thing about the stack—new frames have lower addresses than the old ones so stackoverflows really happen at the beginning of the stack array rather than the end of it (unless you think of arrays as starting at their largest index and ending at 0).
)
Stack is allocated in unit of stack frame.
When a function is called, a stack frame is allocated for it,
When a function returns, its stack frame disappear,
And, stack helps to store function arguments & local variables.
After a function get its stack frame, yes, within the stack frame the function use bytes of it as need dynamic.
Dynamic allocate stack like heap
If u want to allocate memory on stack like the way as heap, then you can use alloca() from <alloca.h>, it's quicker than heap, but in most case u don't need that, it has disadvantages, thus not suggested in general case.
Describe stack allocation in different context might make it more clear:
From the view of a linux thread, (by the way, each process has 1 thread on creation by default, as main thread), the stack is of fix size & allocated on thread creation, (2Mb for IA-32, 32Mb for IA-64, by default), and you can change the default size as need. So you can say this is fix, and static.
From the view of a function within thread or process, the stack frame is allocated for it from the thread's stack memory when the function starts, and the stack frame disappear when the function finish.
From the view of a non-static local variable inside a function, the variable is allocated from the stack frame of the function as need, dynamically.
So, should it be called static or dynamical, you decide.
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?
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