我刚发现以下内容: 正如我所料,在我返回之前释放我的对象会导致应用程序崩溃:
+ (NSString *)descriptionOfExpression:(NSArray *)anExpression {
NSMutableString *expressionDescription;
expressionDescription = [[NSMutableString alloc] init];
for (id object in anExpression) {
//Do stuff to expressionDescription
}
[expressionDescription release];
return expressionDescription;
}
但是,我没想到以下情况会导致内存泄漏:
+ (NSString *)descriptionOfExpression:(NSArray *)anExpression {
NSMutableString *expressionDescription;
expressionDescription = [[NSMutableString alloc] init];
for (id object in anExpression) {
//Do stuff to expressionDescription
}
return expressionDescription;
[expressionDescription release];
}
最终,我的解决方案就是这样做,而不是:
+ (NSString *)descriptionOfExpression:(NSArray *)anExpression {
NSMutableString *expressionDescription;
expressionDescription = [[NSMutableString alloc] init];
for (id object in anExpression) {
//Do stuff to expressionDescription
}
[expressionDescription autorelease];
return expressionDescription;
}
我理解为什么自动释放它有效,但是如何在返回值后释放导致泄漏?
我的第二个问题非常相关:内存泄漏检测系统是否总是正确的?
我意识到开发了仪器和XCode的构建和分析功能的程序员在这方面比我更有经验,所以现在我将假设他们总是正确的。但是,我很难理解像Instruments这样的程序如何“知道”内存被泄露。我认为它应该完全取决于我,程序员,我想要使用一个对象多久。
这是我对“泄密”的理解:
人类定义:如果我在不使用内存时分配了内存,则会泄露内存。
使用计数的编程定义:在分配内存时,内存正在泄漏,但是没有活动对象对相关对象有保留计数。
编程定义使用辅助功能:当存在无法从程序中的任何位置到达的分配内存时,内存正在泄露。
答案 0 :(得分:5)
第二个块的问题是返回后没有代码运行。我原以为Xcode会警告你(看看并尝试修复你的警告,以及错误)
您对泄漏的理解是正确的。构建和分析可能被愚弄 - 它依赖于遵循的编码约定。如果你偏离了这一点,B& A将不知道(或将标记泄漏不是真的)。
泄漏检测仪器会在程序中插入代码以检查您的辅助功能定义。它可能会被强制转换所愚弄,但是如果你只是进行相当简单的分配,分配和发布,我会非常认真地对待它的所有内容,除非你绝对确定它是错误的。
当您返回分配的对象时,请执行以下操作之一
在返回之前调用autorelease - 在这种情况下,调用者负责保留它,如果它想要更长时间。在整个callstack退回到调用你的iOS调用之后释放自动释放的对象 - 这就是“池被耗尽”的地方 - 你应该在返回iOS之前保留它。
将邮件命名为allocSOMETHING或newSOMETHING,不要调用autorelease。在这种情况下,您的消息被理解为返回一个保留计数为1的对象,并且调用者负责释放它(或自动释放它)。
如果您执行上述任一操作,Build and Analyze将理解并帮助您做到正确。
编辑:根据评论添加newSOMETHING
答案 1 :(得分:2)
对于问题的第一部分,答案是基于autorelease实际释放对象的时间。
你问题的第二部分有一个不同的答案。据我所知,泄漏检测系统并不总是正确的,因为它们中的至少一部分是基于启发式的。但是,仪器中的泄漏检测是谨慎的,因此您可以99%确定如果它报告泄漏,那么您确实有泄漏。
它们的工作方式主要是跟踪实际指向的对象。如果它找到一个没有任何指向它但没有被释放的对象,则它被归类为泄漏。
答案 2 :(得分:1)
是内存泄漏检测系统 总是对的?
没有。我对一个不同的问题给出了类似的答案:泄漏工具非常保守。它报告为泄漏的任何东西确实是泄漏,但它不一定报告所有泄漏。静态分析器依赖于了解有关Cocoa / Cocoa Touch API如何工作的规则,因此它也无法始终正确运行。例如,它不知道-[NSTimer invalidate]
释放接收者,因为这不是通用API约定的一部分。