我刚刚发现了以下内容: 如我所料,在我返回之前释放我的对象会导致应用程序崩溃:
+ (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;
}
我明白为什么自动释放会起作用,但是返回值后释放是如何导致泄漏的呢?
我的第二个问题非常相关:内存泄漏检测系统总是正确的吗?
我意识到开发 Instruments 和 XCode 的构建和分析功能的程序员在这方面比我更有经验,所以现在我假设他们总是对的。但是,我很难理解像 Instruments 这样的程序如何“知道”内存正在泄漏。我认为这应该完全取决于我这个程序员想要使用一个对象多长时间。
这是我对“泄漏”的理解:
人的定义:如果我在不使用的时候分配了内存,就是内存泄漏。
使用计数的编程定义:分配内存时内存正在泄漏,但在相关对象上没有具有保留计数的事件对象。
使用辅助功能的编程定义:当分配的内存无法从我现在在程序中的任何位置访问时,内存就会泄漏。
最佳答案
第二个 block 的问题是返回后没有运行代码。我本以为 Xcode 会就此警告您(查看并尝试修复您的警告和错误)
您对泄漏的理解是正确的。构建和分析可能会被愚弄——它依赖于遵循的编码约定。如果您偏离了这一点,B&A 将不会知道(或者会标记不真实的泄漏)。
检漏仪将代码插入到您的程序中以检查您的辅助功能定义。它可能会被转换所愚弄,但如果您只是进行相当简单的分配、分配和释放,我会非常认真地对待它标记的所有内容,除非您绝对确定它是错误的。
当您返回分配的对象时,执行以下操作之一
在返回它之前对其调用 autorelease -- 在这种情况下,如果调用者想要它更长的时间,则调用者负责保留它。在整个调用堆栈展开回调用您的 iOS 调用后,将释放一个自动释放的对象——这就是“池被耗尽”的地方——您应该在返回 iOS 之前保留它。
将您的消息命名为 allocSOMETHING 或 newSOMETHING,并且不要调用 autorelease。在这种情况下,您的消息被理解为返回一个保留计数为 1 的对象,调用者负责释放它(或自动释放它)。
如果您执行其中任一操作,Build and Analyze 将理解并帮助您正确执行。
编辑:根据评论添加新内容
关于iphone - 两个 Objective-C 内存管理问题 : Is Leak Detection Always Right? 和为什么 autorelease 工作但不释放?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4527101/