1

У меня есть эти 4 строки кода внутри функцииCGRect повреждается при передаче в стек

void * someFunction() { 
     ... code to create invocation and other things 
     CGRect aRect; 
     [invocation getReturnValue:&aRect]; 
     finalValue = &aRect; 
     return finalValue 
} 

В принципе, я получаю значение возвращения из NSInvocation и поставить возвращаемое значение по адресу памяти aRect (что AFAIK должен находиться в стеке). Возвращаемое значение, очевидно, является CGRect. someFunction() возвращает указатель на «что-либо». Возвращаемое значение может быть указателем на int, указателем на float или указателем на объект.
Все перечисленные типы возвращаются правильно, но у меня проблема с CGRect.

Debugging, aRect установлен правильно после getReturnValue::

0x07127550 {{0, 20}, {320, 460}} 

Проблема заключается в том, когда я вернусь (код такой же, как и другие типы, INT, длинные или объекта)

// the returned value is a generic pointer 
void * returnValue = someFunction(arguments); 
// cast this generic pointer to a CGRect pointer. 
CGRect returnedRect = *(CGRect *)returnValue; 

результат должен быть возвращен обратно, но отладка снова, CGRect имеет поврежденные значения:

0x07127570 {{-1.99891, 2.61428e-38}, {-1.99891, 2.90066e-38}} 

Как вы можете видеть, адрес памяти одинаков, так что, похоже, прямоугольник был поврежден.

Если изменить первую функцию как это:

 CGRect *aRect = malloc(sizeOfReturnValue); 
     [invocation getReturnValue:aRect]; 
     finalValue = aRect; 
     return finalValue; 

Прямоугольник правильно передается без искажений. Это происходит потому, что в этом случае, я выделил на-структуру кучи

0x08070580 {{0, 20}, {320, 460}} 

Но почему он не работает установив его на стеке? Точный точный код работает правильно для int, float, long и double. Что мне не хватает?

Последнего примечание: Я использую ARC

Благодарность

ответ

3

В коде

void * someFunction() { 
     ... code to create invocation and other things 
     CGRect aRect; 
     [invocation getReturnValue:&aRect]; 
     finalValue = &aRect; 
     return finalValue 
} 

Вы возвращаете адрес временного объекта и вызов неопределенного поведения. aRect недействителен, как только someFunction возвращается.

Когда вы обращаетесь к нему по адресу памяти CGRect returnedRect = *(CGRect *)returnValue;, вы используете память, которая не принадлежит вам, поэтому вы видите странные цифры.

Если вы хотите вернуть CGRect, вы можете просто вернуть объект напрямую. Например

CGRect someFunction() { 
     ... code to create invocation and other things 
     CGRect aRect; 
     [invocation getReturnValue:&aRect]; 
     return aRect; 
} 

и использовать его как

CGRect returnedRect = someFunction(arguments); 
+0

WTF ... ты прав! Я передаю только указатель, поэтому это не может быть указателем на значение стека, потому что когда закончившаяся функция заканчивается, значение становится мусором. Я не могу изменить функцию, чтобы вернуть CGRect, потому что мне нужно вернуть void *, но я могу выделить значение в куче с помощью malloc.По этой причине, даже если он работал (мне повезло), есть проблема даже с int, long, double, поэтому мне тоже нужно изменить этот код. благодаря – LombaX