2012-02-11 87 views
1

在C函数中,调用函数时分配其本地内存,当函数完成时释放本地内存。对于返回值的函数(例如int,string),返回地址的内存是否被分配和释放,并且它是调用堆栈还是被调用堆栈的一部分,还是别的?C中的返回地址的内存分配Objective-C

请看下面的例子:

int* foo() 
{ 
    int _myInt; 
    return(&_myInt); 
} 

这个例子让我完全困惑的内存是如何分配给返回地址返回一个指针。有人可以解释吗?

C和Objective-C相同吗?

+2

没有一个简单的正确答案。您可以从[调用约定](http://en.wikipedia.org/wiki/Calling_convention)和[x86调用约定](http://en.wikipedia.org/wiki/X86_calling_conventions)开始。 – Blastfurnace 2012-02-11 06:22:45

+0

等一下,你在问如何传递参数和结果,或者关于指针返回的内存所有权? – Blastfurnace 2012-02-11 06:30:46

+0

确实返回地址按值或通过引用传递? – KMC 2012-02-11 06:39:41

回答

4

我不知道Objective-C,但是,对于标准C,返回值通常存储在寄存器中。

当函数返回一个指针类型时,由开发人员确保指向的内存在调用后保持有效。

考虑下面的函数:

char* GetStr() 
{ 
    char buff[50]; 
    strcpy(buff, "Hello, World!"); 
    return buff; 
} 

该函数返回一个指针,指向本地存储器,它被释放在函数返回时。访问该内存将构成未定义行为的错误。

这也适用于您的示例,这是无效的。但由于int可以放入寄存器,因此您可以简单地执行return _myInt;并直接返回值。

+0

可以通过将字符串缓冲区声明为static char buff [50]来解决这个问题。 – hotpaw2 2012-02-11 06:16:25

+0

@ hotpaw2:或者从堆中分配内存,或者在函数之外移动声明,或者让调用者提供缓冲区等。 – 2012-02-11 06:17:21

+1

是的,所有解决方案中,使得缓冲区“静态”可能是最不可取的。它从煎锅里掉进火里。 – StilesCrisis 2012-02-11 06:22:51

3

在Obj-C中,如果您通过alloc调用分配了一个对象,则标准做法是在返回之前自动释放该对象,并将该方法命名为调用方知道它正在获取自动释放对象的方式。如果调用者需要,那么它可以再次保留该对象。

- (MyClass *)getMyAutoreleasedObject { 
    MyClass *obj = [[MyClass alloc] init]; 
    return [obj autorelease]; // caller needs to retain if needed 
} 

而且,如果你不那么自动释放你应该在调用者知道它必须释放返回的对象这样的方式命名方法。这是Obj-C严格遵循的惯例。

在C中,如果您在堆栈中分配内存,则该内存在调用者中无效。

int *func() { 
    int a[100]; 
    return a; // invalid in caller 
} 

你的例子有同样的问题。调用者返回的内存无效。在这种情况下,您可以动态分配内存,并且调用者在完成时需要释放内存。

int *func() { 
    int *a = (int *) malloc (100 * sizeof(int)); 
    return a; // caller must free(a) 
} 
3

参数传递给一个函数,返回值传递给调用者。这是如何完成的,完全取决于实施。该语言只需要它的作品,并没有什么可说的如何来做到这一点。

在具有可用寄存器和硬件辅助堆栈的系统上,这些通常用于来回传递值。

不同的类型可能会有不同的处理方式,例如某些CPU具有用于存放指针的专用地址寄存器或单独的浮点寄存器。在这种情况下,这些类型的值可能与整数或结构值的处理方式不同。

传递值的大小也可能会影响它,小值可能适合寄存器,而较大值不适合。

请注意,堆栈不是实现的要求,它只需要使用其他方法来组织值和函数调用。

0

在您的示例函数中,任何对返回值的使用都会调用未定义的行为,因为指向对象的生存期已结束。调用此函数的唯一安全方法是不使用返回值,以便立即丢弃它。