NSMutableArray+C文字列でのメモリリークについて



NSMutableArrayでのメモリリークについてちょっと悩んでましたがしょうもないことで悩んでました。

SQLiteで使用するC文字列をNSMutableArrayに設定しようと思い以下のように作っていました。


- (IBAction)myAction1:(id)sender {
NSMutableArray *muArr = [NSMutableArray arrayWithCapacity:1];

[muArr addObject:@"add1"];

[muArr addObject:[[NSString alloc] initWithUTF8String:"add2"]];
[muArr addObject:[[NSString alloc] initWithUTF8String:"add3"]];

NSMutableArray *muArr2 = [NSMutableArray arrayWithCapacity:1];
[muArr2 addObject:@"add1"];

[muArr2 addObject:[[NSString alloc] initWithUTF8String:"add2"]];
[muArr2 addObject:[[NSString alloc] initWithUTF8String:"add3"]];

[muArr addObject:muArr2];

NSLog([[muArr objectAtIndex:3] description]);
NSLog([muArr description]);
[muArr removeAllObjects];
NSLog([muArr description]);
}

このコードを「Leaks」を使って実行してみると。

f:id:tama-jp:20091103134815p:image

リークが発生していました。

「Build and Anarye」で調べてみました

f:id:tama-jp:20091103134816p:image

4つほどリークが出ていました。

調べてみると

f:id:tama-jp:20091103134817p:image

となっています。

どうやら、


[[NSString alloc] initWithUTF8String:"add2"]
[muArr addObject:[[NSString alloc] initWithUTF8String:"add2"]];

としてしまうと、NSStringに変換した文字列が解放されていないようです。

ですので、いったんNSStringで生成しておき「addObject」でコピーし、

いったん生成したNSStringを解放すればいいのでしょう。

以下のように変更する。


str = [[NSString alloc] initWithUTF8String:"add2"];
[muArr addObject:str]; [str release];

これで、メモリリークはなくなりました。

最初のソースを手直ししてみると以下のようになります。


- (IBAction)myAction1:(id)sender {
NSString *str ;

NSMutableArray *muArr = [NSMutableArray arrayWithCapacity:1];

[muArr addObject:@"add1"];

str = [[NSString alloc] initWithUTF8String:"add2"];
[muArr addObject:str]; [str release];

str = [[NSString alloc] initWithUTF8String:"add3"];
[muArr addObject:str]; [str release];

NSMutableArray *muArr2 = [NSMutableArray arrayWithCapacity:1];
[muArr2 addObject:@"add1"];

str = [[NSString alloc] initWithUTF8String:"add2"];
[muArr2 addObject:str]; [str release];

str = [[NSString alloc] initWithUTF8String:"add3"];
[muArr2 addObject:str]; [str release];

[muArr addObject:muArr2];

NSLog([[muArr objectAtIndex:3] description]);
NSLog([muArr description]);
[muArr removeAllObjects];
NSLog([muArr description]);
}