Question

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

Was it helpful?

Solution

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);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top