From a textbook I was reading, it is said that for functions with a return value, the return value is used to initialize a temporary at the call site.
What I want to know is does that happen before or after the called function exits? In other words, if I have a variable(say, an int) defined inside the called function, will it get destroy before or after the temporary is initialized?
This is the technical view. This might not be interesting to language-lawyers, but for other people, it might me instructive.
A function ends precisely with the branch instruction that transfers control back to the caller. Before this point, the callee has full control, after this point, the caller has full control over what the CPU does. Generally, there is precisely one CPU instruction that is used for this control transfer. On X86-64, that's the ret instruction, PowerPC used blr, other CPUs have other names for the same thing. The name does not matter, though.
Anything, that's within the responsibility of the function itself must happen before this instruction, anything that's none of the callee's business happens somewhere else.
As the caller does not know which variables a function creates, it cannot be the callers responsibility to destruct them. More generally, the callee has to release any stack space that it allocated for its own purposes. As such, the callee must perform such cleanup itself before exiting by issuing the ret instruction. This means, that any local variables must vanish before the function exits.
Things are a bit more complicated when it comes to returning a result from a function: This requires both caller and callee to collaborate. The details differ between the different calling conventions, but there are generally two cases:
The return value is passed in a register.
In this case, the callee will load the return value into a well-known register, and the caller will use that same register to access the return value.
The return value is passed on the stack.
In this case, the callee will place the data that is to be returned at a defined position within the callers stack frame, and the caller will examine that same memory region for the functions result after the call has returned.
TL;DR: If something is a functions responsibility, it must happen before the function returns (= executes the ret instruction). Freeing stack space and returning data to the caller are such responsibilities.
Before
For functions returning by value, the temporary at the call site will be initialized before the scope of the function exits. Otherwise, any return value would be destroyed before it could be passed to the call site.
The Function ends after a return statement
the variables that are declared in that scope will go out of scope and you will not be able to use that unless the variable is declared as static
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.
I know this has probably been asked and I've looked through other answers, but still I cannot get this completely.
I want to understand the difference between the two following codes:
MyClass getClass(){
return MyClass();
}
and
MyClass* returnClass(){
return new MyClass();
}
Now let's say I call such functions in a main:
MyClass what = getClass();
MyClass* who = returnClass();
If I got this straight, in the first case the object created in the
function scope will have automatic storage, i.e. when you exit the
scope of the function its memory block will be freed. Also, before
freeing such memory, the returned object will be copied into the
"what" variable I created. So there will exist only one copy of
the object. Am I correct?
1a. If I'm correct, why is RVO (Return Value Optimization) needed?
In the second case, the object will be allocated through a dynamic storage, i.e. it will exist even out of the function scope. So I need to use a deleteon it. The function returns a pointer to such object, so there's no copy made this time, and performing delete who will free the previously allocated memory. Am I (hopefully) correct?
Also I understand I can do something like this:
MyClass& getClass(){
return MyClass();
}
and then in main:
MyClass who = getClass();
In this way I'm just telling that "who" is the same object as the one created in the function. Though, now we're out of the function scope and thus that object doesn't necessarily exists anymore. So I think this should be avoided in order to avoid trouble, right? (and the same goes for
MyClass* who = &getClass();
which would create a pointer to the local variable).
Bonus question: I assume that anything said till now is also true when returning vector<T>(say, for example, vector<double>), though I miss some pieces.
I know that a vector is allocated in the stack while the things it contains are in the heap, but using vector<T>::clear() is enough to clear such memory.
Now I want to follow the first procedure (i.e. return a vector by value): when the vector will be copied, also the onjects it contains will be copied; but exiting the function scope destroys the first object. Now I have the original objects that are contained nowhere, since their vector has been destroyed and I have no way of deleting such objects that are still in the heap. Or maybe a clear() is performed automatically?
I know that I may beatray some misunderstandings in these subjects (expecially in the vector part), so I hope you can help me clarify them.
Q1. What happens conceptually is the following: you create an object of type MyClass on the stack in the stack frame of getClass.
You then copy that object into the return value of the function, which is a bit of stack that was allocated before the function call to hold this object.
Then the function returns, the temporary gets cleaned up. You copy the return value into the local variable what. So you have one allocation and two copies.
Most (all?) compilers are smart enough to omit the first copy: the temporary is not used except as return value. However, the copy from the return value into the local variable on the caller side cannot be omitted, because the return value lives on a part of the stack that is freed as soon as the function finishes.
Q1a. Return Value Optimization (RVO) is a special feature, that does allow that final copy to be elided. That is, instead of returning the function result on the stack, it will be allocated straight away in the memory allocated for what, avoiding all copying altogether. Note that, contrary to all other compiler optimizations, RVO can change the behaviour of your program! You could give MyClass a non-default copy constructor, that has side effects, like printing a message to the console or liking a post on Facebook. Normally, the compiler is not allowed to remove such function calls unless it can prove that these side effects are absent. However, the C++ specs contain a special exception for RVO, that says that even if the copy constructor does something non-trivial, it is still allowed to omit the return value copy and reduce the whole thing to a single constructor call.
2. In the second case, the MyClass instance is not allocated on the stack, but on the heap. The result of the new operator is an integer: the address of the object on the heap. This is the only point where you will ever be able to obtain this address (provided you didn't use placement new), so you need to hold onto it: if you lose it, you cannot call delete and you will have created a memory leak.
You assign the result of new to a variable whose type is denoted by MyClass* so that the compiler can do type checking and stuff, but in memory it is just an integer large enough to hold an address on your system (32- or 64-bits). You can check this for yourself by trying to coerce the result to a size_t (which is typedef'd to typically an unsigned int or something larger depending on your architecture) and seeing the conversion succeed.
This integer is returned to the caller by value, i.e. on the stack, just as in example (1). So again,
in principle, there is copying going on, but in this case only copying of a single integer which your CPU is very good at (most of the times it will not even go on the stack but get passed in a register) and not the whole MyClass object (which in general has to go on the stack because it's very large, read: larger than an integer).
3. Yes, you should not do that. Your analysis is correct: as the function finishes, the local object is cleaned up and its address becomes meaningless. The problem is, that it sometimes seems to work. Forgetting about optimizations for the time being, the main reason the way memory works: clearing (zero-ing) memory is quite expensive, so that is hardly ever done. Instead, it is just marked as available again, but it's not overwritten until you make another allocation that needs it. Therefore, even though the object is technically dead, its data may still be in the memory so when you dereference the pointer you may still get the right data back. However, since the memory is technically free, it may be overwritten at any time between right now and at the end of the universe. You have created what C++ calls Undefined Behaviour (UB): it may seem to work right now on your computer, but there's no telling what may happen somewhere else or at another point in time.
Bonus: When you return a vector by value, as you remarked, it is not just destroyed: it is first copied to the return value or - taking RVO into account - into the target variable. There are two options now: (1) The copy creates its own objects on the heap, and modifies its internal pointers accordingly. You now have two proper (deep) copies co-existing temporarily -- then when the temporary object goes out of scope, you are just left with the one valid vector. Or (2): When copying the vector, the new copy takes ownership of all the pointers that the old one holds. This is possible, if you know that the old vector is about to be destroyed: rather than re-allocating all the contents again on the heap, you can just move them to the new vector and leave the old one in a sort of half-dead state -- as soon as the function is done cleaning that stack the old vector is no longer there anyway.
Which of these two options is used, is really irrelevant or rather, an implementation detail: they have the same result and whether the compiler is smart enough to choose (2) should not usually be your concern (though in practice option (2) will always happen: deep copying an object just to destroy the original is just pointless and easily avoided).
As long as you realize that the thing that gets copied is the part on the stack and the ownership of the pointers on the heap gets transferred: no copying happens on the heap and nothing gets cleared.
Here are my answers to your different questions:
1- You are absolutely correct. If I understand the sequentiallity correctly, your code will allocate memory, create your object, copy the variable into the what variable, and get destroyed as out of scope. The same thing happens when you do:
int SomeFunction()
{
return 10;
}
This will create a temporary that holds 10 (so allocate), copy it to the return vairbale, and then destroy the temporary (so deallocate) (Here I'm not sure of the specifics, maybe the compiler can remove some stuff via automatic inlining, constante values, ... but you get the idea). Which brings me to
1a- You need RVO when to limit this allocation, copy, and deallocation part. If your class allocates a lot of data upon construction it is a bad idea to return it directly. You can use move constructor in that case, and reuse the storage space allocated by the temporary for example. Or return a pointer. Which takes all the way down to
2- Returning a pointer works exactly as returning an int from a function. But because pointers are only 4 or 8 bytes long, allocation and deallocation cost a lot less than doing so for a class that's 10 Mb long. And instead of copying the object you copy its adress on the heap (usually less heavy, but copy nonetheless). Do not forget it is not because a pointer represents a memory that its size is 0 byte. So using a pointer requires getting the value from some memory address. Returning a reference and inlining are also good ideas to optimise your code, as you avoid chasing pointer, function calls, etc.
3- I think you are correct there. I'd have to make sure by testing, but if follow my logic you are right.
I hope I answered your questions. And I hope my answers are as correct as can be. But maybe someone more clever than me can correct me :-)
Best.
In C++, this pointer get passed to method as a hidden argument which actually points to current object, but where 'this' pointer stored in memory... in stack, heap, data where?
The standard doesn't specify where the this pointer is stored.
When it's passed to a member function in a call of that function, some compilers pass it in a register, and others pass it on the stack. It can also depend on the compiler options.
About the only thing you can be sure of is that this is an rvalue of basic type, so you can't take its address.
It wasn't always that way.
In pre-standard C++ you could assign to this, e.g. in order to indicate constructor failure. This was before exceptions were introduced. The modern standard way of indicating construction failure is to throw an exception, which guarantees an orderly cleanup (if not foiled by the user's code, such as the infamous MFC placement new bug).
The this pointer is allocated on the stack of your class functions (or sometimes a register).
This is however not likely the question you are actually asking.
In C++, this is "simply" a pointer to the current object. It allows you to access object-specific data.
For example, when code in a class has the following snippet:
this->temperature = 40.0f;
it sets the temperature for whatever object is being acted upon (assuming temperature is not a class-level static, shared amongst all objects of the class).
The this pointer itself doesn't have to be allocated (in terms of dynamic memory), it depends entirely on how it's all handled under the covers, something the standard doesn't actually mandate (the standard tends to focus more on behaviour than internals).
There are any number of places it could be: on the stack, at a specific memory location, in a register, and so on. All you have to concern yourself with is its behaviour which is basically how you use it to get access to the object.
What this points to is the object itself and it's usually allocated with new for dynamic allocation, or on the stack.
The this pointer is in the object itself*. Sort of. It is the memory location of the object.
If the object is on the stack, the this pointer is on the stack.
If the object is on the heap, the this pointer is on the heap.
Bottom line, it's nothing you need to worry about.
*[UPDATE] Let me backpedal/clarify/correct my answer. The physical this pointer is not in the object.
I would conclude the this pointer is derived by the compiler and is simply the address of the object which is stored in the symbol table. Semantically, it is inside the object but that was not what the OP was asking.
Here is the memory layout of 3 variables on the stack. The middle one is an object. You can see it holds it's one variable and nothing else:
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.
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;
}