你能简单地检查一个对象的引用是否被分配了一个值nil
来表明它已经被释放了吗?
不,因为向对象发送release
消息和分配nil
给变量是两个不同且不相关的事情。
您可以获得的最接近的是,将任何内容分配给强/保留或复制属性,这会转换为访问器消息,导致该属性的先前值被释放(由设置器完成)。即便如此,观察属性的值——比如使用 KVO——并不意味着你会知道对象什么时候被释放;最特别的是,当拥有对象被释放时,当它直接发送到拥有的对象时,您不会收到通知release
。您还将在控制台中收到一条警告消息(因为拥有对象在您观察它时死亡),并且您不希望来自单元测试的嘈杂警告消息。另外,您必须专门观察每个对象的每个属性才能实现这一点——错过一个,您可能会错过一个错误。
发给对象的release
消息对指向该对象的任何变量都没有影响。释放也不行。
这在ARC下略有变化:nil
当引用的对象消失时,将自动分配弱引用变量。但是,这对您没有多大帮助,因为根据定义,强引用变量不会:如果对对象有强引用,则对象不会(嗯,不应该)消失,因为强引用将(应该)让它活着。一个对象在它应该之前死亡是您正在寻找的问题之一,而不是您想要用作工具的东西。
理论上,您可以为您创建的每个对象创建一个弱引用,但您必须专门引用每个对象,在代码中手动为其创建一个变量。正如你可以想象的那样,巨大的痛苦和肯定会错过物体。
此外,您对实际释放对象的时间有什么保证?
对象通过向其发送release
消息而被释放,因此对象在收到该消息时被释放。
也许您的意思是“解除分配”。释放只是让它更接近那个点。一个对象可以被多次释放,并且如果每次释放仅仅平衡了之前的保留,那么它仍然有很长的生命周期。
对象在最后一次释放时被释放。这会立即发生。正如许多试图写作的聪明人所发现的那样,臭名昭著retainCount
甚至不会降到 0 。while ([obj retainCount] > 0) [obj release];
实际上可能有两个答案:一个使用自动释放池,另一个不使用。
使用自动释放池的解决方案仅适用于自动释放的对象;根据定义,未自动释放的对象不会进入池中。永远不要自动释放某些对象(尤其是您创建的成千上万个对象)是完全有效的,有时也是可取的。此外,您无法查看池中的内容和没有的内容,或者尝试戳每个对象以查看它是否已死。
您将如何编写单元测试(例如,使用 OCUnit)以确保对象在 Cocoa/Objective-C 中被正确释放/保留?
您可以做的最好的事情是设置NSZombieEnabled
为YES
insetUp
并恢复其先前的值 in tearDown
。这将捕获过度释放/保留不足,但不会捕获任何类型的泄漏。
即使您可以编写一个彻底测试内存管理的单元测试,它仍然是不完美的,因为它只能测试可测试的代码——模型对象和可能的某些控制器。您的应用程序中仍然可能存在由视图代码、nib-borne 引用和某些选项(想到“Release When Closed”)等引起的泄漏和崩溃。
您可以编写任何应用程序外测试来确保您的应用程序没有内存错误。
也就是说,像你想象的那样的测试,如果它是独立的和自动的,即使它不能测试所有东西,它也会很酷。所以我希望我错了,有办法。