C 和 Objective-C 中返回地址的内存分配

发布于 2025-01-04 17:27:55 字数 325 浏览 0 评论 0原文

在 C 函数中,其局部内存在调用函数时分配,并在函数完成时释放。对于返回值(例如 int、string)的函数,何时何地返回地址的内存被分配和释放,以及它是否是调用堆栈的一部分或被调用者堆栈,或其他什么?

考虑以下示例:

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

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

C 和 Objective-C 一样吗?

In a C function, its locals's memory is allocated when the function is called, and deallocated when function is finished. What about for functions that return a value (e.g. int, string), when and where does the return address's memory is allocated and deallocated, and is it part of the call stack or the callee stack, or something else?

Consider the following example:

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

This example gets me completely confused as of how memory is allocated for the return address that return a pointer. Can someone please explain?

Same for C and Objective-C?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

琉璃梦幻 2025-01-11 17:27:55

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

当函数返回指针类型时,开发人员需要确保所指向的内存在调用后仍然有效。

考虑以下函数:

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

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

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

I don't know about Objective-C but, with standard C, return values are typically stored in registers.

When the function returns a pointer type, it is up to the developer to ensure the memory pointed to remains valid after the call.

Consider the following function:

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

This function returns a pointer to local memory, which is deallocated when the function returns. Accessing that memory would constitute a bug with undefined behavior.

This also applies to your example, which is not valid. But since an int can fit in a register, you can simply do return _myInt; and return the value directly.

久而酒知 2025-01-11 17:27:55

在 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)
}

In Obj-C if you allocated an object via alloc call then the standard practice is to autorelease that object before returning and name the method is such a way that the caller knows that it is getting an autoreleased object. If the caller needs then it can retain that object again.

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

And if you do not autorelease then you should name the method in such a way that the caller knows that it must release the returned object. This is a strictly followed convention in Obj-C.

In C, if you allocate memory in stack then that memory is not valid in caller.

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

Your example has the same problem. The returned memory is invalid in caller. In this case you can allocate the memory dynamically and the caller needs to free that when done.

int *func() {
    int *a = (int *) malloc (100 * sizeof(int));
    return a;  // caller must free(a)
}
嘿咻 2025-01-11 17:27:55

参数被传递给函数,返回值被传递回调用者。如何做到这一点完全取决于实施。该语言只要求它能够工作,而没有说明如何做到这一点。

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

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

传递的值的大小也可能会影响它,小值可以容纳在寄存器中,而较大的值则不能。

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

Parameters are passed to a function, and return values are passed back to the caller. How that is done is totally up to the implementation. The language only requires that it works and has nothing to say about how to do it.

On systems with available registers and a hardware assisted stack, these are generally used for passing the values back and forth.

Different types might be treated differently, for example some CPUs have dedicated address registers that hold pointers, or separate floating point registers. In that case values of those types might be handled differently from integer or struct values.

The size of the values passed might also affect it, small value could fit in a register while larger values would not.

Note that a stack is not a requirement for an implementation, it just has to use some other method for organizing values and function calls.

人心善变 2025-01-11 17:27:55

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

In your example function, any use of the return value whatsoever will invoke undefined behavior, since the lifetime of the pointed-to object has ended. The only safe way to call this function is without using the return value so that it is immediately discarded.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文