开发者

Warning "Potential leak of an object allocated on line ..." when declaring a 2D array

Initially i declared a 2D array in this way:

subUrb = [[NSArray alloc] initWithObjects:
     [[NSArray alloc] initWithObjects:ALL_SUBURBS_LABEL, @"East",@"South", @"West", @"North", nil] ,
     [[NSArray alloc] initWithObjects:ALL_SUBURBS_LABEL, @"Kuala Lumpur SubUrb1", @"Kuala Lumpur SubUrb2", nil],
     [[NSArray alloc] initWithObjects:ALL_SUBURBS_LABEL, @"Jakarta SubUrb1",nil],
     nil]; 

But when i try to 'analyze' the warnings of the project, i got three same type of issues in this chunk of code - "potential leak of an object allocated on line xxx"

I noticed that to get rid of it, i have to write sth like this:

subUrb = 
    [[NSArray alloc] initWithObjects:
        [[[NSArray alloc] initWithObjects:ALL_SUBURBS_LABEL, @"East",@"South", @"West", @"North", nil] autorelease],
        [[[NSArray alloc] initWithObjects:ALL_SUBURBS_LABEL, @"Kuala Lumpur SubUrb1", @"Kuala Lumpur SubUrb2", nil] autorelease],
        [[[NSArray alloc] initWithObjects:ALL_SUBURBS_LABEL, @"Jakarta SubUrb1",nil] autorelease],
        nil];

Then i will开发者_开发知识库 not get any analyze warnings. But i dun like this...it is not logical. This 2D array should never be released in my controller actually, the entire 2D array should be retained for the entire life time of the controller for a PickerView.

How should I declare the 2D array more elegantly?


1: NARC

If you send +alloc, you own that object and it is your responsibility to release it. Hence

[[NSArray alloc] initWithObjects:ALL_SUBURBS_LABEL, @"East",@"South", @"West", @"North", nil]

creates an array that’s owned by you, hence you should release it.

2: Cocoa collections own their elements

When you add an object to a Cocoa collection such as NSArray, the collection owns that object. It will also release all elements in the collection when they’re not used any longer.

3: Conclusion

Your code without -autorelease gives you ownership of both the outermost array and each inner array that’s an element of the outermost array. This means that you’re responsible for releasing those four arrays (one outermost, three innermost). However, since the outermost array already owns the innermost arrays, you probably don’t need to own them as well, hence -autorelease.


You get the ownership if you allocate an array with alloc init and so you have to release it as you do in your second code. You can also use: [[NSArray alloc] initWithObjects: [NSArray arayWithObjects:first,second, nil], nil];


Your second method is correct. The point is that the enclosing array will take ownership of the nested objects, while the additional ownership lien you gain via alloc is left dangling. A marginally neater approach is to use the class method arrayWithObjects instead of alloc/initWithObjects/autorelease but it amounts to the same thing.


Even if the array is needed through the entire life of the controller, you should release it on the controller's dealloc method, otherwise the objects will leak.


If it is never released then both ways won't leak, but the second is more "correct". The NSArrays won't be autoreleased till the parent array is (never), so it is fine.


When you add a child array to the parent array, the parent array retains the child array. Thus increasing the retain count to 2. Since you're aren't keeping a reference to the child array(s) anywhere else the retain count should only be 1, hence you should use autorelease. So your second version is correct.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜