Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 使用NSNumber对象的NSArray文本的Objective-C内存问题_Ios_Objective C_Memory Management_Memory Leaks_Nsarray - Fatal编程技术网

Ios 使用NSNumber对象的NSArray文本的Objective-C内存问题

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

我最近开始学习Objective-C,试图了解内存管理。昨天我遇到了一个奇怪的问题,它导致了超过150MB的内存泄漏!我将其追溯到一段代码,该代码创建了NSNumbers的NSArray文本。我使用NSMutableArray(使用addObject)成功地解决了这个问题,但是我还不能理解为什么一个方法有效而另一个方法无效。我希望有人能对内存管理有更好的理解,来解释它背后的概念,这样我将来就可以避免这样的错误

为了更好地说明我的问题,让我也提供代码片段。例如,我有一个函数,它创建了一个由几个NSNumber组成的NSArray并返回它,它被多次调用:

-(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卡上进行过测试