我可以找到关于僵尸的问题,但没有一个直接解决它们是什么以及它们发生的原因和方式。在回答特定问题的背景下,有一些解决了僵尸进程的问题,但没有解决原因。
还有关于僵尸进程的问题以及有关Objective-C / Cocoa相关僵尸对象的问题。有什么区别或这些有何关系? Mac / iPhone上的“EXEC_BAD_ACCESS”(或其他平台上的类似错误)是僵尸的代名词吗?
如何阻止僵尸,是否有任何有助于避免僵尸的最佳做法?
将这些信息放在一个地方会很有帮助。如果可能,这个问题旨在与平台/语言无关。
答案 0 :(得分:34)
僵尸进程和僵尸对象是完全无关的。僵尸进程是指父进程启动子进程并且子进程结束,但父进程没有获取子进程的退出代码。进程对象必须保持不变,直到发生这种情况 - 它不会消耗资源而且已经死了,但它仍然存在 - 因此,“僵尸”。
Zombie 对象是Cocoa / CoreFoundation的一个调试功能,可以帮助您捕获内存错误 - 通常当对象的refcount降为零时,它会立即释放,但这会使调试变得困难。相反,如果启用了僵尸对象,则对象的内存不会立即释放,它只是标记为僵尸,并且将记录任何进一步尝试使用它的情况,并且您可以跟踪对象在其生命周期中使用的位置。
EXEC_BAD_ACCESS是您的普通“你使用了一个糟糕的指针”异常,就像我做的那样:
(*(0x42)) = 5;
答案 1 :(得分:8)
当一个进程结束时,它的大部分状态仍然存在于内核中,因为它的父进程可能仍然想要查看一些东西,比如它的返回值,它需要存储在某个地方。当一个父调用wait()或waitpid()时,它会告诉内核把它全部扔掉,因为它完成了它。在这之前,孩子会保留一个pid并耗尽资源。那些未收获的子进程被称为僵尸。即使杀死一个僵尸也不会删除它,它必须由其父级获得(等待)。如果父级死亡,它们将在unix系统上传递给“init”,其唯一的工作就是等待事情清理它们。
我从来没有听说过“僵尸对象”,但我认为它指的是那些没有被垃圾收集器清理过的东西,或者那些带有循环引用或某些东西的东西,这样他们就不会由垃圾收集器清理。这个比喻非常相似:fork()== malloc(),wait()== free()在某个级别。 (当然不是一个完美的比喻。)