how can we clean the stack...
return statement is used to go out from the function. now
if (m1.high_[0] < m2.low_[0]) return FALSE;
here it have m1 and m2 two points with high[0],low[0], low[1] and high[1] values..
now if we use return with statement than is this clean the stack.. i mean return statement with if condition is used to clean the stack.. is it?
You dont really "clean" the stack. All that happens is the stack pointer is reset to top of the calling programs stack storage.
Any subsequent function called from this program will be given the same stack pointer as your program receieved (including any values set by your program -- which is why its important to intialise automatic storage!)
Conversly when your program invokes a function the called function will be given a stack pointer of just after the last piece of your stack, and, if you call more than one function they will all end up with the same stack pointer.
To clarify C C++ programs support three types of storage allocation:-
"static" which is effectivly global to the compile unit. A suitable lump of storage is allocated when the main program starts and each "static" is allocated an address in this lump of starage. Which is used until the main program terminates.
"heap" this is a collection of storage areas managed by "malloc" with a little help from the underlying operating system. Most (but not all!) "new" objects allicate memory this way.
Then "automatic" storage (which is the default) uses the stack. Again this is fairly large contiguous area of storage allocated whne your main program starts. Any automatic variables used by "main" will be allocated to the begining of the stack and the stack pointer incremented to point to the word after the end of main's last variable.
When the first function is called it allocates its automatic variables starting from the current stack pointer and the stck pointer is set to the word after the end of its last variable, if if calls other functions then the process is repeated. When a function ends the stack pointer is reset to whatever value it had when the function was called.
In this way storage is constantly reused without the need for any mallocs or frees and it makes it easy to implement recursive functions as each call will get its own piece fo the stack (until the stack runs out!).
Yes, whenever a function returns by executing 'return XXXX', the stack frame for the concerned function is removed. Local automatic storage duration objects are destroyed in this process. Also it may involve manipulation of certain CPU registers (e.g. ESP, EBP on Intel) and is an implementation specific behavior. It does not matter if the return statement is executed in a condition or on the value which is being returned
EDIT 2:
In the code below, the local object 's' (which has automatic storage duration) is destroyed. The local object 'p' and 'x' are also destroyed, but the memory pointed to by 'p' which was newe'd is not deleted automatically until explicitly deleted is done (using delete). All this happens irrespective of when the function 'f' returns via 'return true' or 'return false'
struct S{};
bool f(int x){
S s;
S *p = new S;
if(x == 2) return true;
else return false;
}
Related
Hi i want to ask how the EBP and ESP registers are initialized and updated during program execution.
I have an image below and the author explains that when entering a new function, first the arguments are pushed onto the stack shown in the yellow region, then the base pointer EBP is updated and the base pointer of the previous function stored, followed by stack allocating more resources for local variables and return addresses.
I want to know wouldn't it be easier to simply update the base pointer when entering the new function, then allocate memory for the previous function's base pointer register address, followed by the arguments, local variables and return value? Instead of having the EBP in the middle of a stack frame for a function.
My other question is, where exactly does the return address value point to in the previous function, is it at the end of the previous function, or the start of the previous function?
My other question is, what significance does storing the previous function base pointer register if you already store the return address of the previous function?
The idea i get from pointers is that you essentially just want to use them as a reference for accessing resources local to a function, you can do with the return address
Thanks
To return from a function you need to restore (at least) two things.
One is where the instruction pointer is, what the next instruction you are running it located at.
The other is where the stack pointer is, where the data you are operating is.
(Depending on calling convention, registers may also have to be reset, but I don't know details here).
The return address -- the instruction pointer -- points to where the code should continue executing when returned from the call. This isn't usually either the start or end of the calling function, but rather the "next instruction" after the call. (But not really; it points to the code that handles the return from the function, which in some calling conventions does real work).
The code calling a function has to update the stack pointer so that the called function knows where its on-stack arguments are, and provide enough information for the called function to return.
The function called has no need to do that internally. It (well, the compiler writing it knows) what variables it has put on the stack, and how big they are. The set of variables on the stack may vary over time during the body of the function. So updating the stack pointer is pointless, and would even make offset calculations a bit more complex (as they keep on changing, instead of being constant for a given "variable") and confusing for an assembly writer.
Code that accesses the stack does so with an offset regardless. Not changing the stack pointer is doing less work than changing the stack pointer, and doing less work usually is faster than doing more work.
So you leave the stack pointer alone, unless you need to change it.
The return address is useless for accessing mutable data. The return address points at usually read-only machine code, not at mutable state on the stack.
Now, there are plenty of calling conventions in the wild. Many of them do slightly different things. Which arguments go on the stack, which are stored in registers, what kind of arguments go where, and who resets the stack pointer (the caller or the callee) can vary, among other things.
When the memory is allocated to a function.
For example:
int doubleMe(int smthng){
int dbl = 2*smthng; //line 2
return dbl;
}
void main(){
int var;
printf("The double of var is: %d",doubleMe(var)); //line 8
}
When is memory allocated to variable dbl?
when is defined (line 2) (compile time)
or when function is called (line 8)(run time)
I believe it is allocated when function is called(run-time) in stack. And freed when function exits, is it? Would be great if someone could please explain it better.
This question looks similar but not quite!
The compiler generates object code of a function when it is defined. The generated code contains instructions to allocate memory in the stack for function local variables or it can use registers to accomodate them.
Where a function is called the compiler generates object code of the function call and corresponding instructions to push arguments on the stack. At this point the compiler may not to know how the function is defined and whether it is defined because its definition can be in some other module or library.
Take into account that the compiler may inline functions even if you yourself do not use function specifier inline. In this case it will place the function definition in the point where the function is called.
Memory is allocated to variable dbl(or var) at compile time in the stack memory
Not correct, it is allocated in run-time, just as all other stack variables. That's the whole point of using a stack. It is allocated when your function is called, in run-time.
I believe it is allocated when function is called. And freed when function exits, is it?
Yes.
Regarding your statement: Memory is allocated to variable dbl(or var) at compile time
No, The instructions to allocate memory are created at compile time.
Memory is not allocated until that function is executed.
Memory created inside a function is an example of local scope memory. if it is created on the stack, it will be released upon leaving the scope in which it was created. If it was created on the heap (i.e. created using [m/c/re]alloc() functions) it will not be released (or more accurately, made available as described here) until free() is called, or at program exit.
Later, you state:
I believe it is allocated when function is called. And freed when function exits.
This statement is true, but this all happens at run-time only. Not at compile-time.
For global scope memory, stack memory is created when the program is executed, and is not released until the program ends. Again, for heap memory , it will be released upon calling free(), or at program exit.
It's not allocated during compilation at all, but at runtime.
When the function is called during execution, either space will be reserved for it in memory (in approximately 100% of current C++ implementations, "on the stack") or it will reside in a register.
If it's not in a register, the space is freed when the function returns.
The compiler produces code that will perform the runtime allocation, if there is any.
People always talk about how objects created without the new keyword are destroyed when they go out of scope, but when I think about this, it seems like that's wrong. Perhaps the destructor is called when the variable goes out of scope, but how do we know that it is no longer taking up space in the stack? For example, consider the following:
void DoSomething()
{
{
My_Object obj;
obj.DoSomethingElse();
}
AnotherFuncCall();
}
Is it guaranteed that obj will not be saved on the stack when AnotherFuncCall is executed? Because people are always saying it, there must be some truth to what they say, so I assume that the destructor must be called when obj goes out of scope, before AnotherFuncCall. Is that a fair assumption?
You are confusing two different concepts.
Yes, your object's destructor will be called when it leaves its enclosing scope. This is guaranteed by the standard.
No, there is no guarantee that an implementation of the language uses a stack to implement automatic storage (i.e., what you refer to as "stack allocated objects".)
Since most compilers use a fixed size stack I'm not even sure what your question is. It is typically implemented as a fixed size memory region where a pointer move is all that is required to "clean up" the stack as that memory will be used again soon enough.
So, since the memory region used to implement a stack is fixed in size there is no need to set the memory your object took to 0 or something else. It can live there until it is needed again, no harm done.
I believe it depends where in the stack the object was created. If it was on the bottom (assuming stack grows down) then I think the second function may overwrite the destroyed objects space. If the object was inside the stack, then probably that space is wasted, since all further objects would have to be shifted.
Your stack is not dynamically allocated and deallocated, it's just there. Your objects constructors and destructors will get called but you don't get the memory back.
Because people are always saying it, there must be some truth to what they say, so I assume that the destructor must be called when obj goes out of scope, before AnotherFuncCall. Is that a fair assumption?
This is correct. Note that this final question says nothing about a stack". Whether an implementation uses a stack, or something else, is up to the implementation.
Objects created "on the stack" in local scope have what is called automatic storage duration. The Standard says:
C++03 3.7.2 Automatic storage duration
1/ Local objects explicitly declared auto or register or not
explicitly declared static or extern have automatic storage duration.
The storage for these objects lasts until the block in which they are
created exits.
2/ [Note: these objects are initialized and destroyed as described in
6.7. ]
On the destruction of these objects:
6.7 Declaration statement
2/ Variables with automatic storage duration (3.7.2) are initialized
each time their declaration-statement is executed. Variables with
automatic storage duration declared in the block are destroyed on exit
from the block (6.6).
Hence, according to the Standard, when object with local scope fall out of scope, the destructor is called and the storage is released.
Weather or not that storage is on a stack the Standard doesn't say. It just says the storage is released, wherever it might be.
Some architectures don't have stacks in the same sense a PC has. C++ is meant to work on any kind of programmable device. That's why it never mentions anything about stacks, heaps, etc.
On a typical PC-type platform running Windows and user-mode code, these automatic variables are stored on a stack. These stacks are fixed-size, and are created when the thread starts. As they become instantiated, they take up more of the space on the stack, and the stack pointer moves. If you allocate enough of these variables, you will overflow the stack and your program will die an ugly death.
Try running this on a Windows PC and see what happens for an example:
int main()
{
int boom[10000000];
for( int* it = &boom[0]; it != &boom[sizeof(boom)/sizeof(boom[0])]; ++it )
*it = 42;
}
What people say is indeed true. The object still remains in the memory location. However, the way stack works means that the object does not take any memory space from stack.
What usually happens when memory is allocated on the stack is that the stack pointer is decremented by sizeof(type) and when the variable goes out of scope and the object is freed, the stack pointer is incremented, thus shrinking the effective size of data allocated on the stack. Indeed, the data still resides in it's original address, it is not destroyed or deleted at all.
And just to clarify, the C++ standard says absolutely nothing about this! The C++ standard is completely unaware of anything called stack or heap in sense of memory allocation because they are platform specific implementation details.
Your local variables on stack do not take extra memory. The system provides some memory from each thread's stack, and the variables on the stack just use part of it. After running out of the scope, the compiler can reuse the same part of the stack for other variables (used later in the same function).
how do we know that it is no longer taking up space in the stack?
We don't. There are way to see whether they do or don't, but those are architecture and ABI specific. Generally, functions do pop whatever they pushed to the stack when they return control to the caller. What C/C++ guarantees is that it will call a destructor of high-level objects when they leave the scope (though some older C++ like MSVC 6 had terrible bugs at a time when they did not).
Is it guaranteed that obj will not be saved on the stack when AnotherFuncCall is executed?
No. It is up to the compiler to decide when and how to push and pop stack frames as long as that way complies with ABI requirements.
The question "Is something taking up space in the stack" is a bit of a loaded question, because in reality, there is no such thing as free space (at a hardware level.) A lot of people (myself included, at one point) thought that space on a computer is freed by actually clearing it, i.e. changing the data to zeroes. However, this is actually not the case, as doing so would be a lot of extra work. It takes less time to do nothing to memory than it does to clear it. So if you don't need to clear it, don't! This is true for the stack as well as files you delete from your computer. (Ever noticed that "emptying the recycle bin" takes less time than copying those same files to another folder? That's why - they're not actually deleted, the computer just forgets where they're stored.)
Generally speaking, most hardware stacks are implemented with a stack pointer, which tells the CPU where the next empty slot in the stack is. (Or the most recent item pushed on the stack, again, this depends on the CPU architecture.)
When you enter a function, the assembly code subtracts from the stack pointer to create enough room for your local variables, etc. Once the function ends, and you exit scope, the stack pointer is increased by the same amount it was originally decreased, before returning. This increasing of the stack pointer is what is meant by "the local variables on the stack have been freed." It's less that they've been freed and more like "the CPU is now willing to overwrite them with whatever it wants to without a second thought."
Now you may be asking, if our local variables from a previous scope still exist, why can't we use them? Reason being, there's no guarantee they'll still be there from the time you exit scope and the time you try to read them again.
because obj, the playingCard object is created inside a nested for loop does that mean after the second for loop completes, obj gets deallocated from the stack each time?
and a small side question,
does a compiler use the stack (similar to recursion) to keep track of loops and nested loops?
for(int c = 0;c<nElems;c++) {
for(int z = c + 1;z<nElems;z++) {
playingCard obj;
}
}
It gets constructed and deconstructed every iteration.
However, on the stack, the concept of allocation is (for at least VS and GCC) more hazy. Since the stack is a contiguous block of memory, premanaged by the compiler, there's no real concept of allocating and deallocating in the way that there is for heap allocations (new/delete or malloc/free). The compiler uses the memory it needs on the stack, and simply rolls back the pointer later on.
The scope of the object is in with-in the enclosing braces [ whether it is a function or loop brace ]. so, as soon as the scope ends, the destructor of the object gets called and the object gets deallocated.
Coming to your second question, depends on the compiler to maintain its own strategy to handle the loops and keep track of the objects.
It gets allocated/deallocated on every iteration of your inner loop.
I'm not clear on your side question, but the compiler uses the stack to keep track of all local variables that it can't otherwise just squeeze into registers.
Objects in the stack are allocated or deallocated once (even if they are nested in loops). However, constructors and destructors are called on every iteration.
Assume I have a function like this:
MyClass &MyFunction(void)
{
static MyClass *ptr = 0;
if (ptr == 0)
ptr = new MyClass;
return MyClass;
}
The question is at program exit time, will the ptr variable ever become invalid (i.e. the contents of that ptr are cleaned up by the exiting process)? I realize that this function leaks, but it is only an example for simplicity.
The same question also applies to other primitives besides pointers as well. How about if I have a static integer, does the value of that integer always persist throughout exit or is variable due to static destruction order issues?
EDIT:
Just to clarify, I want to know what actually happens to the contents of the static pointer (or any other primitive type like an int or a float) and not to the memory it is pointing to. For instance, imagine that the ptr points to some memory address which I want to check in the destructor of some other static class. Can I rely on the fact that the contents of the ptr won't be changed (i.e. that the pointer value won't be cleaned up during the static destruction process)?
Thanks,
Joe
When you process exits the all memory pages allocated to it will be freed by the OS (modulo shared memory pages that someone else may be using).
However, as others point out the destructor for MyClass is never called. Nor is the value pointed to by ptr ever changed. If you have a static int with the value 123 then its value will stay 123 through to the very end of the process' lifetime.
In modern operating systems, all of an application's memory is allocated on a "heap" specific to that application. When the application exits, all of the memory in that heap will be freed.
So, the memory will be deallocated, but: the destructor for MyClass will never be called. This can be an issue if the destructor is responsible for releasing any non-memory resources (file system locks are a common example).
To answer your question:
'imagine that the ptr points to some memory address which I want to check in the destructor of some other static class'
The answer is yes.
You can see the value of the pointer (the address).
You can look at the content if you have not called delete on the pointer.
Static function variables behave in the same way as static class variables and global variables (aka non local static), in that there destructors will be called in reverse order of creation. Integers, floats and pointers (POD) do not have destructors so nothing happens to them until the processes is removed.
POD objects: Data can safely by referenced from the destructor of other objects (even global s).
Other static objects (i.e. those with destructors): In the general case, it is not safe to accesses these objects after main() has exited because the order of destruction is not know (it is the reverse of the order of creation, but the order of creation is complex see: Construction Order ). It can be done but you have to take explicit precautions to make sure the object is still alive.
Note: non local static:
The memory will always be there, the object will just not be valid after a destructor is called (note POD does not have a destructor).
Note: Stack:
Only valid until the scope in which they are declared is left.
After the stack is popped the memory page that it is on could potentially be dropped resulting in SEG faults if you attempt to access it.
Note: Heap:
Valid until you call delete on the pointer that allocated it.
Once a pointer is delete the value is potentially random as it may be re-used.
Potentially the page the memory was on can also be dropped. Any access to a dropped page would result in a SEG fault.
To answer your updated question, I would say yes: you can rely on the value of that static pointer remaining throughout the static destruction process. The memory it points to may have been freed, but the value of the pointer itself should remain unchanged, unless the destructor of another static class makes a change to it.
The short answer is "no": your pointer will not "become invalid" at program exit time. I.e. the pointer value will not automatically be reset to null, and destructor of the MyClass object to which it points will not automatically be called.
This is because a pointer is a "primitive type", i.e. not an object.
If you have a non-local (i.e. global or static) variable which is an object, then the rules are different: the destructor of the object will be called when the program terminates by calling exit() or by returning from the main function. It will not be called if the program terminates by calling abort().