NSArray Memory Management

限于喜欢 提交于 2019-12-13 03:03:52

问题


For some reason when I release the NSArray I get the EXC_BAD_ACCESS exception. Here is the implementation:

-(void) loadAllAlphabets
{
    NSBundle *bundle = [NSBundle mainBundle]; 
    NSArray *imagesPath = [[NSArray alloc] init]; 

    imagesPath = [bundle pathsForResourcesOfType:@"png" inDirectory:@"Images"];

    alphabets = [[NSMutableArray alloc] init]; 

    NSString *fileName = [[NSString alloc] init]; 

    for(int i=0; i<= imagesPath.count -1 ; i++) 
    {
        fileName = [[imagesPath objectAtIndex:i] lastPathComponent];
        CCSprite *sprite = [CCSprite spriteWithFile:fileName];

        sprite.userData = [[fileName stringByDeletingPathExtension] uppercaseString];   

        [alphabets addObject:sprite]; 
    }

    // release fileName 
    [fileName release]; 
    fileName = nil; 

    [imagesPath release]; // this causes the application to crash with EXC_BAD_ACCESS
//  imagesPath = nil; 

}

UPDATE 1:

So, the problem was that although I was responsible for releasing the imagesPath object since I used alloc that soon become irrelevant when pathsForResourcesOfType returned an autorelease object. This means I should not release the imagesPath object manually.

The following line should be used:

NSArray *imagesPath = [bundle pathsForResourcesOfType:@"png" inDirectory:@"Images"];

UPDATE 2:

Another question which is related to this post. In the following code I initialize a new NSMutableArray manually.

alphabets = [[NSMutableArray alloc] init]; 

Later I insert CCSprite (Cocos2d objects) into alphabets array. CCSprite are autorelease objects. Do I still have to release alphabets manually? Since, after some time all objects are released and memory will be returned but then what will be left inside alphabets NSMutable array?


回答1:


general rule of thumb in memory management - you should release an object only if you obtain it using method that contains new, copy or alloc in it (standard method follow that rule and you should stick to it as well).

In your case you obtain imagesPath object using pathsForResourcesOfType: method which returns an autoreleased object so you must not release it yourself.

Edit: yes, you need to release alphabets object somewhere (for the same reason - you got it with alloc method).

Objective-c containers take an ownership of objects added to them, that us when objects are added to an array they get retained so it is guaranteed that their life time is at least as long as the life time of container. When you remove object from collection or collection itself is destroyed then its members get released (to compensate retain on add).




回答2:


I think the confusion is here:

NSArray *imagesPath = [[NSArray alloc] init]; 
imagesPath = [bundle pathsForResourcesOfType:@"png" inDirectory:@"Images"];

The first line creates a new object. This object really needs to be released.

The second line over-writes that object with a new, self-managed object. This does not need to be manually release.

This means that you're leaking the first imagesPath.

In general, you need to release an object if you alloc or copy it. And you shouldn't over-write an object before you release (or autorelease) its content.




回答3:


Also, you are leaking memory as you initialize imagesPath with an empty non-mutable array and then discard it when you assign he result of pathsForResources: to it. Just do this instead:

NSArray *imagesPath = [bundle pathsForResourcesOfType:@"png" inDirectory:@"Images"];

Same error with fileName. Not need to initialize it with an empty non mutable string.

And also do not release fileName since it is also an autoreleased object.



来源:https://stackoverflow.com/questions/3668919/nsarray-memory-management

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!