I have these 4 lines of code inside a function
void * someFunction() {
... code to create invocation and other things
CGRect aRect;
[invocation getReturnValue:&aRect];
finalValue = &aRect;
return finalValue
}
Basically, I get the return value from an NSInvocation
and put the returned value at the memory address of aRect (that, AFAIK, should be on the stack). The return value is obviously a CGRect.
someFunction() returns a pointer to "anything". The returned value can be a pointer to int, a pointer to float, or a pointer to an object.
All the mentioned types returns correctly, but I have a problem with CGRect.
Debugging, aRect is set correctly after getReturnValue:
:
0x07127550 {{0, 20}, {320, 460}}
The problem is when I return (the code is the same as the other types, int, long, or object)
// the returned value is a generic pointer
void * returnValue = someFunction(arguments);
// cast this generic pointer to a CGRect pointer.
CGRect returnedRect = *(CGRect *)returnValue;
the result should go into returnedRect, but debugging again, the CGRect has corrupted values:
0x07127570 {{-1.99891, 2.61428e-38}, {-1.99891, 2.90066e-38}}
As you can see, the memory address is the same, so the rect seems to have been corrupted.
If I change the first function like this:
CGRect *aRect = malloc(sizeOfReturnValue);
[invocation getReturnValue:aRect];
finalValue = aRect;
return finalValue;
the rect is passed correctly without corruption. This happens because, in this case, I've allocated the struct on the heap
0x08070580 {{0, 20}, {320, 460}}
But why it doesn't work setting it on the stack? The same exact code works correctly for int, float, long, and double. What am I missing?
Last note: I'm using ARC
Thanks
In your code
void * someFunction() {
... code to create invocation and other things
CGRect aRect;
[invocation getReturnValue:&aRect];
finalValue = &aRect;
return finalValue
}
You're returning an address of a temporary object and invoking undefined behavior. aRect
is invalid as soon as someFunction
returns.
When you access it the memory address in CGRect returnedRect = *(CGRect *)returnValue;
you're using memory that doesn't belong to you hence why you're seeing weird numbers.
If you want to return the CGRect, you could just return the object directly. For example
CGRect someFunction() {
... code to create invocation and other things
CGRect aRect;
[invocation getReturnValue:&aRect];
return aRect;
}
and use it like
CGRect returnedRect = someFunction(arguments);