Objective c 为什么我可以在[super Dealoc]之后释放ivar而不进行分段?

Objective c 为什么我可以在[super Dealoc]之后释放ivar而不进行分段?,objective-c,cocoa,memory-management,dealloc,Objective C,Cocoa,Memory Management,Dealloc,似乎在Objective-C中,负责内存分配的方法(如C中的malloc())是-[NSObject alloc]。释放那些记忆怎么样?这是由-[NSObject dealloc]完成的吗?这就是为什么在我们自己的类的dealloc中,我们必须调用[super dealloc]最后一个,而不是第一个 我问这个问题是因为我不明白为什么,如果我先把[super dealoc]放在前面,然后在下一行使用[\u bar release]释放一个对象,我就不会出现分段错误。运行[super dealoc]

似乎在Objective-C中,负责内存分配的方法(如C中的
malloc()
)是
-[NSObject alloc]
。释放那些记忆怎么样?这是由
-[NSObject dealloc]
完成的吗?这就是为什么在我们自己的类的
dealloc
中,我们必须调用
[super dealloc]
最后一个,而不是第一个


我问这个问题是因为我不明白为什么,如果我先把
[super dealoc]
放在前面,然后在下一行使用
[\u bar release]
释放一个对象,我就不会出现分段错误。运行
[super dealoc]
后,如果释放对象的内存,
\u bar
应该已经是不属于进程的内存块。

-dealoc
最终释放与Objective-C对象关联的内存(可能通过
free()
,但这是一个实现细节。)在
-dealloc
之后,您能够发送消息的唯一原因是未定义的行为。发送
[super dealloc]
后,发送给
self
或其IVAR的任何进一步消息都是不安全的。

我想你是说,你有以下代码:

- (void)dealloc
{
    [super dealloc];
    [_bar release]; // _bar is a member variable
}
您希望在第二行中出现分段错误,但实际上并非如此

原因是运气

操作系统将捕获对进程不拥有的内存的访问,但它不会监控进程内发生的所有事情。在本例中,您正在访问已标记为空闲的内存,但它仍然属于您的进程,因此行为未定义。内存在几毫秒前是有效的,因此可能还没有人开始重用这一页内存,因此它可能仍然有有效的数据。所以它可能会成功。但它也可能失败

这是错误的代码,您不应该发送它。但是仅仅因为它是不正确的和未定义的并不意味着它不会工作。

在最简单的“概念”情况下,NSObject的
dealoc
例程执行
free
操作,镜像
alloc
例程中完成的
malloc
。在实践中可能会有所不同,但只要概念模型得到满足,这些都是无稽之谈


如果你把
[super dealloc]
放在(预弧)
dealloc
例程的第一位,它基本上不会出现分段故障,因为空间在释放时没有时间被其他对象覆盖(并且在释放时它不会物理上消失——它只是进入“可用”列表中)。

是的,
alloc
是完成分配的地方。请注意,它可能完成,也可能不完成,有时根本没有分配(这是一个实现细节)。分配通常发生在
alloc
NSObject
实现中

如果分配了内存,那么对
dealloc
的链式调用就是最终释放内存的调用

调用
[super dealloc]
后,您不应该访问实例变量。这并不意味着,如果你这样做,你会得到一个错误。你可以也可以不犯错误,这是未定义的行为

但是,需要记住的一件重要事情是,除了在dealloc实现本身中调用
[super dealloc]
之外,您永远不应该直接调用
dealloc
。目标C为参考计数。当您处理完一个对象时,您不会解除锁定它。相反,您可以
释放它(或者
自动释放它,如果您完成了,但是您正在将它返回给调用者,并且不知道调用者是否会使用它)。当系统确定不再有人引用该对象时,将自动调用
dealloc

编辑:

我要澄清一下,有时根本没有分配。事实上,如果调用alloc,通常会发生分配,但是init*方法可能会撤销它。通常,对
alloc
的所有调用之后都应立即调用其中一个初始值设定项。但是,初始化者不需要初始化他们接收的
self
。相反,它们可以去掉它(从而释放内存),并返回一个完全不同的对象,该对象可能会被分配,也可能不会被分配


因此,在这种情况下,
alloc
分配的内存实际上是由初始值设定项释放的(可以调用也可以不调用
dealloc
)。初始化后得到的对象可能是一个静态对象,它没有在堆上分配,永远不会被释放。它也可能是一个非指针(无效地址),被强制转换为
(void*)
(又称
id
)并返回。

请重新表述您的问题。我读了两遍,我不明白你在问什么。Objective-C使用C函数获取内存和释放内存,对吗?因此它使用
malloc
free
。问题是,在Objective-C中完成的地方在哪里?您是否在问Objective-C运行时在哪里完成(实现细节,我们不知道/关心),或者您作为开发人员应该在哪里使用malloc/free?(如果你用主动语态而不是被动语态,你的写作会更清晰。)我认为,一般来说,我们不会在Objective-C中使用malloc或free,所以我想问的是,我们知道Objective-C确实分配内存并释放内存,因为它是基于C的,所以它发生在哪里以及如何发生。我们可以说它是Objective-C的一个实现细节,但它应该清楚它的位置,我认为它应该是基类的
-dealoc
在Xcode的scheme编辑器中启用MallocScribble。上面的代码每次都会崩溃,因为free()上的内存会被显式破坏。因此,如果不打开它,它可能不会崩溃?我之前在想,也许它是自由的,但也是自由的