当在for循环中使用NSString时,内存泄漏

时间:2022-02-15 08:59:26

I have 100 images in my resource bundle named like image1.jpg,image2.jpg. Basically what i am trying to do is create path names to those images dynamically inside a for loop.
While testing in simulator,the images loaded fine and the app did not crash.But while testing the app with instruments i was shocked to see the heavy memory leak that was happening while i was creating the path1 object.

我的资源包中有100幅图片,比如image1.jpg、image2.jpg。基本上我要做的就是在for循环中动态创建这些图像的路径名。在模拟器中测试时,图像加载良好,应用程序没有崩溃。但当我用仪器测试这款应用时,我震惊地看到在我创建path1对象时发生了严重的内存泄漏。

     I am pasting  the entire method here for reference

- (id)init {
self = [super init];
if (self) {             

    self.arrayImages = [[[NSMutableArray alloc] init] autorelease];      

    for(int i=1 ; i<100 ; i++){            

        NSString *str = [NSString stringWithFormat:@"Century%d",i];
        NSString *path1 = [[NSBundle mainBundle] pathForResource:str ofType:@"jpg"];            
        [self.arrayImages addObject:path1];        
    }                        
}
return self;

}

}

As i have not made use of any alloc inside the loop i dont have any ownership and hence no right to release the object.What is the reason for this memory leak??

由于我没有在循环中使用任何alloc,我没有任何所有权,因此也没有释放对象的权利。内存泄漏的原因是什么?

Kindly explain the problem and provide the necessary solution in order to fix it..

请解释问题,并提供必要的解决方案。

As always,any help is highly appreciated..

一如既往,我们非常感谢您的帮助。

3 个解决方案

#1


3  

arrayImages is retaining path1, and so if you do not release arrayImages it will leak. How are you creating arrayImages, and are you releasing it anywhere?

arrayImages保留了path1,因此如果不释放arrayimage,它将会泄漏。你是如何创建arrayImages的,你在哪里发布它?

Edited based on comments:

编辑基于评论:

Make sure you release arrayImages in your -dealloc method like so: [arrayImages release]; (note the lack of self).

确保在-dealloc方法中释放arrayImages,比如:[arrayImages释放];(注意缺乏自我)。

#2


2  

There is no leak in the code you've shown.

您所显示的代码没有漏洞。

There are (at least) two possibilities:

(至少)有两种可能性:

  1. You have a leak in code you didn't paste into your question
  2. 你有一个代码漏洞,你没有粘贴到你的问题
  3. Everything is fine and Instruments gave you a false-positive
  4. 一切都很好,仪器给你一个假阳性

Your loop will create a lot of autoreleased variables. These won't be deallocated until after the loop has finished, but that's how it's supposed to work.

您的循环将创建许多自定义变量。在循环完成之后,这些将不会被释放,但这是它应该工作的方式。

#3


-1  

The reason for the leak would be this line right here:

泄露的原因是这条线:

NSString *str = [NSString stringWithFormat:@"Century%d",i];

By using convenience methods in Objective-C, what happens in the background is the following:

使用Objective-C中的便利方法,在后台发生的情况如下:

NSString *str = [[[NSString alloc] initWithFormat:@"Century%d", i] autorelease];

Not using alloc/init to create a weak reference is a misconception. You are always the owner of a created object, no matter how you create it. The convenience method simply does the alloc/init and autoreleases it for you.

不使用alloc/init创建弱引用是一种误解。无论如何创建,您始终是已创建对象的所有者。便利的方法只是做alloc/init,并自动为您发送。

Here's what I would suggest you do to avoid leaking memory:

为了避免内存泄漏,我建议你这样做:

- (id)init {
    self = [super init];
    if (self) {             

        self.arrayImages = [[[NSMutableArray alloc] init] autorelease];

        NSAutoreleasePool *tmpPool = [[NSAutoreleasePool alloc] init];

        for(int i = 1 ; i < 100 ; i++) {

            NSString *str = [NSString stringWithFormat:@"Century%d",i];
            NSString *path1 = [[NSString alloc] initWithString:[[NSBundle mainBundle] pathForResource:str ofType:@"jpg"]];
            [self.arrayImages addObject:path1];
            [path1 release];
        }

        [tmpPool drain];
    }
    return self;
}

Let me know if this works better for you.

如果这样对你更好的话,请告诉我。

-EDIT- Allocating the path1 object and releasing it after adding to arrayImages.

-编辑-分配path1对象并在添加到arrayImages后释放它。

#1


3  

arrayImages is retaining path1, and so if you do not release arrayImages it will leak. How are you creating arrayImages, and are you releasing it anywhere?

arrayImages保留了path1,因此如果不释放arrayimage,它将会泄漏。你是如何创建arrayImages的,你在哪里发布它?

Edited based on comments:

编辑基于评论:

Make sure you release arrayImages in your -dealloc method like so: [arrayImages release]; (note the lack of self).

确保在-dealloc方法中释放arrayImages,比如:[arrayImages释放];(注意缺乏自我)。

#2


2  

There is no leak in the code you've shown.

您所显示的代码没有漏洞。

There are (at least) two possibilities:

(至少)有两种可能性:

  1. You have a leak in code you didn't paste into your question
  2. 你有一个代码漏洞,你没有粘贴到你的问题
  3. Everything is fine and Instruments gave you a false-positive
  4. 一切都很好,仪器给你一个假阳性

Your loop will create a lot of autoreleased variables. These won't be deallocated until after the loop has finished, but that's how it's supposed to work.

您的循环将创建许多自定义变量。在循环完成之后,这些将不会被释放,但这是它应该工作的方式。

#3


-1  

The reason for the leak would be this line right here:

泄露的原因是这条线:

NSString *str = [NSString stringWithFormat:@"Century%d",i];

By using convenience methods in Objective-C, what happens in the background is the following:

使用Objective-C中的便利方法,在后台发生的情况如下:

NSString *str = [[[NSString alloc] initWithFormat:@"Century%d", i] autorelease];

Not using alloc/init to create a weak reference is a misconception. You are always the owner of a created object, no matter how you create it. The convenience method simply does the alloc/init and autoreleases it for you.

不使用alloc/init创建弱引用是一种误解。无论如何创建,您始终是已创建对象的所有者。便利的方法只是做alloc/init,并自动为您发送。

Here's what I would suggest you do to avoid leaking memory:

为了避免内存泄漏,我建议你这样做:

- (id)init {
    self = [super init];
    if (self) {             

        self.arrayImages = [[[NSMutableArray alloc] init] autorelease];

        NSAutoreleasePool *tmpPool = [[NSAutoreleasePool alloc] init];

        for(int i = 1 ; i < 100 ; i++) {

            NSString *str = [NSString stringWithFormat:@"Century%d",i];
            NSString *path1 = [[NSString alloc] initWithString:[[NSBundle mainBundle] pathForResource:str ofType:@"jpg"]];
            [self.arrayImages addObject:path1];
            [path1 release];
        }

        [tmpPool drain];
    }
    return self;
}

Let me know if this works better for you.

如果这样对你更好的话,请告诉我。

-EDIT- Allocating the path1 object and releasing it after adding to arrayImages.

-编辑-分配path1对象并在添加到arrayImages后释放它。