传递堆栈时CGRect被破坏

时间:2013-08-08 23:10:20

标签: objective-c memory-management return-value cgrect nsinvocation

我在函数

中有这4行代码
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的问题。

调试,在getReturnValue:

之后正确设置了aRect
0x07127550 {{0, 20}, {320, 460}}

问题是当我返回时(代码与其他类型,int,long或object相同)

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

结果应该进入returnRect,但是再次调试,CGRect的值已损坏:

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

如您所见,内存地址相同,因此rect似乎已损坏。

如果我更改第一个功能:

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

正确传递rect而不会损坏。 发生这种情况是因为,在这种情况下,我已经在堆上分配了结构

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

但为什么它不能在堆栈上设置呢? 完全相同的代码适用于int,float,long和double。 我错过了什么?

最后注意:我正在使用ARC

由于

1 个答案:

答案 0 :(得分:3)

在您的代码中

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

您正在返回临时对象的地址并调用未定义的行为。 <{1}}返回时aRect无效。

当您访问someFunction中的内存地址时,您正在使用不属于您的内存,因此您会看到奇怪的数字。

如果要返回CGRect,可以直接返回对象。例如

CGRect returnedRect = *(CGRect *)returnValue;

并像

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