Objective c 目标C/iOS:使用ARC释放内存(内存泄漏)
我不熟悉iOS/Objective-C,我不能正确理解内存的释放。 为了测试它,我创建了一个空的Objective c 目标C/iOS:使用ARC释放内存(内存泄漏),objective-c,ios,memory-leaks,automatic-ref-counting,Objective C,Ios,Memory Leaks,Automatic Ref Counting,我不熟悉iOS/Objective-C,我不能正确理解内存的释放。 为了测试它,我创建了一个空的ARC启用的iPhone项目,并创建了一个非常简单的测试类: #import "MemTest.h" @implementation MemTest { } -(void) start { for (int i = 0; i < 1500000; i++) { NSMutableString *myString = [NSMutableString string];
ARC
启用的iPhone项目,并创建了一个非常简单的测试类:
#import "MemTest.h"
@implementation MemTest {
}
-(void) start {
for (int i = 0; i < 1500000; i++) {
NSMutableString *myString = [NSMutableString string];
// The appended string is 2000 characters long in the real test class.
[myString appendString:@"12345678901234567890123456 <very long>"];
if (i % 1000 == 0) {
NSLog(@"i = %d", i);
}
myString = nil;
}
}
@end
应用程序(如预期)打印了许多漂亮的数字“i=xy”,但内存使用量随着每次迭代而增加,最后应用程序崩溃:
....
2012-12-06 20:17:40.193 MemTestApp[19250:11303] i = 930000
2012-12-06 20:17:40.208 MemTestApp[19250:11303] i = 931000
MemTestApp(19250,0xac63f2c0) malloc: *** mmap(size=16777216) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
所以我的问题是:为什么内存使用量在增长
我认为通过分配nil,当使用
ARC
时,应该释放内存。我在这里遗漏了什么?一些事情可能会出错:
-保留,并确保抛出编译器错误
-O0
(无优化)时,它通常不会阻止对象进入自动释放池。这很可能就是你正在发生的事情@autoreleasepool{}
粘贴在for
循环中,您会发现内存使用应该消失。或者,您可以尝试使用[NSMutableString]
,而不是使用[NSMutableString new]
,它根本不使用自动释放池*但在ARC代码中的行为应该相同
*嗯,NSMutableString
可以自由地在内部使用autorelease池
所以我的问题是:为什么内存使用量在增长
因为所有的分配都是在一个循环中进行的。所有这些字符串都是自动释放的对象,当顶部的自动释放池被清空时,它们就会被清除,这在每次运行循环中都会发生。但您根本没有给运行循环一个运行的机会,因此自动释放池永远不会耗尽,内存也不会耗尽
ARC使您不用担心管理单个对象,但您仍然需要了解,因为ARC根据相同的规则工作。方法返回一个“autoreleased”对象。这意味着对象被放入“自动释放”池。当池被耗尽时,对象将被释放(并且,如果不再有对它的强引用,它将被释放)。自动释放池在运行循环结束时自动排空(就在系统进入睡眠等待另一个事件之前) 在编写可能分配大量自动释放对象的循环时,可能需要管理自己的自动释放池:
-(void) start {
for (int i = 0; i < 1500000; i++) {
@autoreleasepool {
NSMutableString *myString = [NSMutableString string];
...
}
}
}
-(无效)开始{
对于(int i=0;i<1500000;i++){
@自动释放池{
NSMutableString*myString=[NSMutableString];
...
}
}
}
该代码在每个循环迭代开始时创建一个新的自动释放池,并在每个循环迭代结束时将其耗尽。因此,您创建的每个字符串都将在循环结束时释放,并且在您的示例代码中,由于没有其他内容保留它,因此将被释放
有关更多信息,请阅读,特别是“使用自动释放池块”一章。我不认为自动释放的对象会以不同的方式释放,只是因为您的项目具有ARC。实际上,autorelease池的工作方式与此完全相同:因为您在循环中分配了大量对象,所以在迭代时池永远不会耗尽 您应该尝试直接在循环体内部强制一个新的
自动释放池
,看看这是否解决了您的问题。当然,这可能有些过分,您可以尝试将循环拆分为两个嵌套的循环,以便不时拥有一个自动释放池,例如
for (int i = 0; i < TOTAL_STEPS; ++i) {
@autoreleasepool {
for (int j = 0; j < STEP_SIZE; ++j) {
..
}
}
}
for(int i=0;i
我甚至不认为将局部变量设置为
nil
会对您的情况产生影响,因为它是循环体范围的局部变量,编译器已经知道您不能在其他任何地方使用它。谢谢您的回答!他们把事情弄清楚了。在循环中使用自动释放池实现了这一点。但是我从你的回答中得到的主要信息是:我必须阅读更多关于内存管理的内容另一件需要注意的事情是,僵尸通常在方案中打开:诊断,这意味着在释放对象时,实际上不会删除任何内存。这将使自动释放池看起来也会泄漏。在这种情况下,我该怎么办
for (int i = 0; i < TOTAL_STEPS; ++i) {
@autoreleasepool {
for (int j = 0; j < STEP_SIZE; ++j) {
..
}
}
}