Ios 使用NSNumber对象的NSArray文本的Objective-C内存问题
我最近开始学习Objective-C,试图了解内存管理。昨天我遇到了一个奇怪的问题,它导致了超过150MB的内存泄漏!我将其追溯到一段代码,该代码创建了NSNumbers的NSArray文本。我使用NSMutableArray(使用addObject)成功地解决了这个问题,但是我还不能理解为什么一个方法有效而另一个方法无效。我希望有人能对内存管理有更好的理解,来解释它背后的概念,这样我将来就可以避免这样的错误 为了更好地说明我的问题,让我也提供代码片段。例如,我有一个函数,它创建了一个由几个NSNumber组成的NSArray并返回它,它被多次调用:Ios 使用NSNumber对象的NSArray文本的Objective-C内存问题,ios,objective-c,memory-management,memory-leaks,nsarray,Ios,Objective C,Memory Management,Memory Leaks,Nsarray,我最近开始学习Objective-C,试图了解内存管理。昨天我遇到了一个奇怪的问题,它导致了超过150MB的内存泄漏!我将其追溯到一段代码,该代码创建了NSNumbers的NSArray文本。我使用NSMutableArray(使用addObject)成功地解决了这个问题,但是我还不能理解为什么一个方法有效而另一个方法无效。我希望有人能对内存管理有更好的理解,来解释它背后的概念,这样我将来就可以避免这样的错误 为了更好地说明我的问题,让我也提供代码片段。例如,我有一个函数,它创建了一个由几个NS
-(NSArray *)getNSNumberArray
{
float num1 = 23.56;
float num2 = 75.34;
float num3 = 223.56;
NSArray *numArray = @[[NSNumber numberWithFloat:num1], [NSNumber numberWithFloat:num2], [NSNumber numberWithFloat:num3]];
return numArray;
}
-(void)causeMemoryLeak
{
for (int i = 0; i < 2000000; i++)
{
NSArray *recieverArray = [self getNSNumberArray];
}
}
-(NSArray*)getNSNumberArray
{
浮点数m1=23.56;
浮点数m2=75.34;
浮点数m3=223.56;
NSArray*numArray=@[[NSNumber numberWithFloat:num1]、[NSNumber numberWithFloat:num2]、[NSNumber numberWithFloat:num3];
返回努马拉;
}
-(无效)因果关系
{
对于(int i=0;i<2000000;i++)
{
NSArray*ReceiveArray=[self getNSNumberArray];
}
}
这导致iphone6上的内存占用超过200MB。但是,如果我将功能更改为:
-(NSArray *)getNSNumberArray
{
float num1 = 23.56;
float num2 = 75.34;
float num3 = 223.56;
NSMutableArray *numMutableArray = [[NSMutableArray alloc] init];
NSNumber *nsNumber1 = [NSNumber numberWithFloat:num1];
NSNumber *nsNumber2 = [NSNumber numberWithFloat:num2];
NSNumber *nsNumber3 = [NSNumber numberWithFloat:num3];
[numMutableArray addObject:nsNumber1];
[numMutableArray addObject:nsNumber2];
[numMutableArray addObject:nsNumber3];
return numMutableArray;
}
-(void)causeMemoryLeak
{
for (int i = 0; i < 2000000; i++)
{
NSArray *recieverArray = [self getNSNumberArray];
}
}
-(NSArray*)getNSNumberArray
{
浮点数m1=23.56;
浮点数m2=75.34;
浮点数m3=223.56;
NSMutableArray*numMutableArray=[[NSMutableArray alloc]init];
NSNumber*nsNumber1=[NSNumber numberWithFloat:num1];
NSNumber*nsNumber2=[NSNumber numberWithFloat:num2];
NSNumber*nsNumber3=[NSNumber numberWithFloat:num3];
[numMutableArray addObject:nsNumber1];
[numMutableArray addObject:nsNumber2];
[numMutableArray addObject:nsNumber3];
返回numMutableArray;
}
-(无效)因果关系
{
对于(int i=0;i<2000000;i++)
{
NSArray*ReceiveArray=[self getNSNumberArray];
}
}
这不会导致任何内存问题
也许我错过了一些非常明显的东西,但仍然无法找出背后的原因。我真的很感谢你在这方面的帮助。也可能有更好的方法,这样的答案是受欢迎的,但基本上我在寻找背后的解释
非常感谢
连接到显示设备(iphone 6)内存分配的屏幕截图的链接(目前我无法在此处连接图像,因此必须提供链接)
方法1内存分配(内存保留而非释放):
方法2内存分配(内存被释放,内存分配也没有激增):正如您所说,只有一种方法会导致内存激增,但似乎并非如此。根据文档,NSMutableArray使用的内存稍多一些,因为它可以更改大小,不能在对象内部存储内容,必须存储指向离线存储的指针以及存储的额外malloc节点 在这两种方法中,内存被立即释放,我没有任何问题 更新1: 我注意到,如果您使用该数组,例如,如果您记录该数组,则在第一种方法中内存会立即释放。这是因为您不使用该数组。它解决了您的问题。请尝试以下代码:
-(NSArray *)getNSNumberArray
{
float num1 = 23.56;
float num2 = 75.34;
float num3 = 223.56;
NSArray *numArray = @[[NSNumber numberWithFloat:num1], [NSNumber numberWithFloat:num2], [NSNumber numberWithFloat:num3]];
return numArray;
}
-(void)causeMemoryLeak
{
for (int i = 0; i < 2000000; i++)
{
NSArray *recieverArray = [self getNSNumberArray];
NSLog(@"%@", recieverArray);
}
}
-(NSArray*)getNSNumberArray
{
浮点数m1=23.56;
浮点数m2=75.34;
浮点数m3=223.56;
NSArray*numArray=@[[NSNumber numberWithFloat:num1]、[NSNumber numberWithFloat:num2]、[NSNumber numberWithFloat:num3];
返回努马拉;
}
-(无效)因果关系
{
对于(int i=0;i<2000000;i++)
{
NSArray*ReceiveArray=[self getNSNumberArray];
NSLog(@“%@”,接收阵列);
}
}
我尝试了你的代码,因为我真的没有找到内存泄漏的任何原因,也没有内存泄漏
使用常规数组时,设备将运行所有代码,并仅在最后释放内存。这将导致堆分配250 MB,并在最后释放它们
如果您使用可变数组,那么设备会在创建新数组之前释放以前的数组,因此对多个数组的分配没有意义
我想这可能是由于循环中被调用函数的运行时复杂性造成的。首先,您需要阅读“自动释放”和“自动释放池”。对象通常保存在自动释放池中,只有在自动释放池消失时才会消失。因此,循环迭代200万次而不使用自动释放池是一个坏主意。实际上没有内存泄漏,在方法返回后的某个时间,对象都将被释放 大多数返回对象的方法都返回自动释放的对象,但是[[xxx alloc]init]的结果不是自动释放的,因此存在差异。但是ARC也非常聪明,如果一个方法返回一个自动释放的对象,并且调用方立即保留该对象,那么该对象实际上不会被添加到自动释放池中。这就是当对象被传递到NSLog时发生的情况;为了做到这一点,必须首先保留它。没有自动释放池。在您的代码中,从未使用过对象,因此没有进行优化
当然你的代码真的没用,所以你因为写了没用的代码而受到惩罚 2000000次调用只是为了显示明显的内存泄漏。在这两种方法中,函数被调用了2000000次。我刚刚更改了这两种方法中的函数体。问题是,在第一种方法中,内存被保留而不是释放,而在第二种方法中内存被释放。试图找出背后的原因。@IndieGameDevLearner检查更新的答案。我已经添加了截图,两种方法的内存都达到了200+mb。谢谢你的快速回复。您是否在实际的设备或sim卡上进行过测试