在堆栈上存储对象

时间:2011-08-08 20:54:53

标签: objective-c memory-management

是否可以为堆栈上的对象分配空间?我不想参加比赛 语言原则,是的,自动发布池工作得非常好。它的 只是好奇心(以及调查它)。我听说过的事情 像:

struct {
    Class isa;
} s_obj;

s_obj.isa = [NSObject class];

NSObject *obj = (NSObject *)&s_obj;

但我不确定这是否能正常运作。至少,它听起来不是很好 实用,因为需要重新创建对象的结构。

也许覆盖+alloc,然后以某种方式调用alloca() 场景?看起来像是在allocWithZone:中传递一个不同的区域 最好的方法,但NSZone是完全无证的。 CocoaDev has an article 在它上面,但我不知道这是不是要走的路。有什么想法吗?

最终,如果出现一个易于使用的解决方案,那么使用它会很好 除了已经存在的语言功能。

2 个答案:

答案 0 :(得分:5)

都能跟得上;不能那样做。或者,从技术上讲,可以,但是您无法将对象传递给任何系统API,并且不能继承NSObject。

系统假定对象在堆中; autorelease将按预期工作,并且可以通过管理保留的引用来控制对象的生命周期,对于堆栈分配的对象,这些引用都不会成立。

(有一个例外;块有时会从堆栈开始。非常特殊的情况,它完全由编译器控制。它也让人们吵起来。)


alloca()不起作用;内存将在进行分配的帧中“分配”(堆栈指针将被碰撞)。一旦你尝试返回对象,分配就是gunk,返回的引用现在是一个悬空指针。

除了声明外,

NSZone已被弃用。为了在1994年左右快速销毁,OpenStep试图使基于区域的分配永久化。事实证明太脆弱了;有太多方法可以将对区域的引用转移到另一个区域,并且区域破坏会产生悬空指针。


捕获Daniel的问题评论中的内容

  • 一旦包含堆栈分配对象的堆栈帧被销毁,对该对象的任何引用都将无效。因此,任何引用的消息都将具有未定义的行为,并且很可能并且最多会彻底崩溃。即您无法将保留计数设置为某个超高值,因为对release的调用已经太晚了,因为它将通过现在无效的对象引用取消引用以尝试获取isa以尝试并执行该方法。

  • 你不能在这样的对象中继承NSObject,因为NSObject带有一大堆功能,包括KVO,KVC和相关对象等公共功能,以及各种私有实现细节。系统框架。任何此功能都可以随时保留/释放/自动释放实例,因为基本上retain保证对象的生命周期,直到release子类化NSObject 时。

  • 您无法测试“工作”行为,因为与系统提供框架的保留/释放/自动释放相关的任何假设都是固有的实现细节,可能因任何原因而在任何软件更新中发生变化。

答案 1 :(得分:-1)

理论上,您可以获得一大堆堆栈存储(例如char[NN])并将其传递给init。 [或者可能不是 - 目前尚不清楚代码如何决定调用哪个init - 至少可能需要先设置类。]未知(和未记录/不支持)的内容是其余的代码取决于初始化alloc的作用。当然,引用计数将无效(并且可能以某种方式初始化为大值)。当然,dealloc不会在帧退出时被调用,并且需要明确调用它的精简版本。