frank wrote:os64dev wrote:I may not be correct about this but I have always assumed that it will return a copy of the object. If he were to return a pointer to the ret object it would not work.
And where should the compiler put the copy of the object? It might work if you have something RECT x = CreateRect(0,0,100,100) and defined a copy constructor but that is an assumption. However in general i live to the rule: "assumption is the mother of all fuckups" and therefore use the heap.
Sorry I may be crazy but I am pretty sure that I read somewhere that if you are returning an object from a function it returns a copy of the object ie it keeps a copy on the stack and upon returning from the function is copies the object from the stack into the object you specify. (Obj o = Get_Obj( ); // o in this case )
If I am wrong about this then please someone correct me. I really would like to know the truth about it.
<ignore>
Yes, but it does not actually return a object on the stack instead the
l-value being assigned to by the function call is passed to the function as a pointer (on the stack).
</ignore>
<correction>
from the function is copies the object from the stack into the object you specify.
--- I just reread what you wrote. Yes. You are correct.
</correction>
Take for instance:
Code: Select all
struct sA{
unsigned long a, b, c;
};
struct sA fA(struct sA a)
{
++a.a;
++a.b;
++a.c;
return a;
}
int main()
{
struct sA a = {0, 0, 0};
struct sA b;
b = fA(a);
return 1;
}
When looking at
b = fA(a) you would think that the object would be placed on the stack then copied into
b, but instead, even with no optimizations, a pointer to
b is actually passed as the first argument to the function where the values are written using this pointer where
return a is.
The same should happen with:
Code: Select all
sA fA(unsigned long a, unsigned long b, unsigned long c)
{
sA ret;
ret.a = a; ret.b = b; ret.c = c;
return ret;
}
The
sA ret is allocated on the stack (in the current frame), then assignments are made to this while lastly the first invisible argument to the function is a pointer to the actual instance of the variable you are using as a assignment. With optimization turned on I would imagine that it would eliminate the local variable
ret, and just do a straight assignment to the return value (pointer to return value).
Code: Select all
08048344 <fA>:
8048344: 55 push %ebp
8048345: 89 e5 mov %esp,%ebp
/////////// pointer to return structure has been placed into edx.
8048347: 8b 55 08 mov 0x8(%ebp),%edx
/////////// operations follow modifying the argument passed via stack. (copied onto the stack, rather)
804834a: 8b 45 0c mov 0xc(%ebp),%eax
804834d: 40 inc %eax
804834e: 89 45 0c mov %eax,0xc(%ebp)
8048351: 8b 45 10 mov 0x10(%ebp),%eax
8048354: 40 inc %eax
8048355: 89 45 10 mov %eax,0x10(%ebp)
8048358: 8b 45 14 mov 0x14(%ebp),%eax
804835b: 40 inc %eax
804835c: 89 45 14 mov %eax,0x14(%ebp)
804835f: 8b 45 0c mov 0xc(%ebp),%eax
/////////// edx is a pointer to the return value, here it copies.
8048362: 89 02 mov %eax,(%edx)
8048364: 8b 45 10 mov 0x10(%ebp),%eax
8048367: 89 42 04 mov %eax,0x4(%edx)
804836a: 8b 45 14 mov 0x14(%ebp),%eax
804836d: 89 42 08 mov %eax,0x8(%edx)
8048370: 89 d0 mov %edx,%eax
8048372: 5d pop %ebp
/////////// it is making the return value a pointer to where it placed the data, edx == eax.
8048373: c2 04 00 ret $0x4
So it should be o-kay to return a function local variable or structure, but not a pointer to that local variable or structure since the pointer will reference a address on the stack that will be overwritten through stack manipulation very shortly or later on.