2011-06-29 14 views
0

OK、私は壁を運転しているメモリ管理の問題があります。ある時点で問題なく動作していると私は誓っていますが、今ではどこにでもメモリが漏れていて、理由を理解できません。OS Xアプリのメモリリークに困惑しました

まず、NSTaskを開始してから、タスクの実行中にループを実行しています。

- (void)encodeProgressTimer 
{ 
    if ([[NSUserDefaults standardUserDefaults] boolForKey:@"menuProgress"]) { 
    // Read the last line 
NSString *fileData = [NSString stringWithContentsOfFile:encodingOutput encoding:NSASCIIStringEncoding error:nil]; 
    NSArray *lines = [fileData componentsSeparatedByString:@"\r"]; 
    NSString *lastLine = [lines objectAtIndex:[lines count] - 1]; 
    NSString *percent; 
    NSString *eta; 
    BOOL dataFound = NO; 
    if ([lastLine length] == 71) { 
     dataFound = YES; 
     percentRange = (NSRange) {23,5}; 
     etaRange = (NSRange) {61,9}; 
     percent = [lastLine substringWithRange:percentRange]; 
     eta = [lastLine substringWithRange:etaRange]; 
    } 
    else if ([lastLine length] == 72) { 
     dataFound = YES; 
     percentRange = (NSRange) {23,5}; 
     etaRange = (NSRange) {62,9}; 
     percent = [lastLine substringWithRange:percentRange]; 
     eta = [lastLine substringWithRange:etaRange]; 
    } 
    else if ([lastLine length] == 70) { 
     dataFound = YES; 
     percentRange = (NSRange) {23,5}; 
     etaRange = (NSRange) {60,9}; 
     percent = [lastLine substringWithRange:percentRange]; 
     eta = [lastLine substringWithRange:etaRange]; 
    } 

    if (dataFound) { 
     NSMutableString *bottomStr = [[NSMutableString alloc] 
            initWithFormat:@"Encoding: %@%% - ETA %@", percent, eta]; 
       [appDelegate setMenuTop:topString andBottom:bottomStr]; 
     [bottomStr release]; 
    } 

} 

}

それは何も、私は特に割り当てていないよというのが私の理解だと:encodeProgessTimer方法がSTDOUTからの最後の行をつかみ、メニューバーのことを置いている

NSTask *encodingTask = [[NSTask alloc] init]; 
      NSFileHandle *taskStdout = [NSFileHandle fileHandleForWritingAtPath:encodingOutput]; 
      [encodingTask setStandardOutput:taskStdout]; 
      [encodingTask setStandardError:taskStdout]; 
NSString argString = [NSString stingWithString: @"some arguments"]; 
[encodingTask setArguments:taskArgs]; 
      [encodingTask setLaunchPath:somePath]; 
      [encodingTask launch]; 

while ([encodingTask isRunning]){ 
       sleep(1); 
       [self encodeProgressTimer]; 
      } 

メソッドが完了したら初期化は自動的に解放されるべきですが、そうではありません。これが呼び出されると、毎秒メモリ使用量が指数関数的に上がります。私が自分の記憶量を見ると、生きているCFstingsの数が屋根を通ります。私がencodeProgressTimerを回すと、私の問題は解消されます。私は、メモリ使用量を非常に安定させたencodeProgressTimerに自動解放プールを追加しようとしましたが、20分ほど実行した後にEXC_BAD_ACCESSを取得しました。ゾンビをオンにするにいることになります:

*** -[NSConcreteAttributedString _drawCenteredVerticallyInRect:scrollable:]: message sent to deallocated instance 0x2bc756e0 

私は実際に通過したと、それはのalloc/initの対応だに各変数の宣言を変更し、それらを手動でリリースしたが、それはどちらかの問題を解決しませんでした。この時点で私はかなり困惑しています。

はまた、完全を期すために[appDelegate setMenuTop:andBottom:]メソッドは次のようになります。

-(void) setMenuTop: (NSString *) top andBottom: (NSString *) bottom 
{ 
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"menuProgress"]) { 
    [statusItem setImage:nil]; 
    NSMutableParagraphStyle *lineHeight = [[NSMutableParagraphStyle alloc] init]; 
    [lineHeight setMaximumLineHeight:10.5]; 
    [lineHeight setLineBreakMode:NSLineBreakByTruncatingMiddle]; 
    OperationQueue *opQueue = [OperationQueue sharedQueue]; 
    NSString *sBuffer = [[NSMutableString alloc] initWithFormat: @"%@ (%i More)\n%@", top, [opQueue queueCount] - 1, bottom]; 
    attributes = [[NSDictionary alloc] initWithObjectsAndKeys:[NSFont menuFontOfSize:9], NSFontAttributeName, lineHeight, NSParagraphStyleAttributeName, nil]; 
    if (statusTitle) 
     [statusTitle release]; 
    statusTitle = [[NSAttributedString alloc] initWithString: sBuffer attributes: attributes]; 
    [statusItem setAttributedTitle: statusTitle]; 
    [lineHeight release]; 
    [sBuffer release]; 
    [attributes release]; 
    } 

}

答えて

1

自動解放プールには負荷がかかりますが、メモリを解放するには明示的に排除する必要があります。次のようにwhileループを変更します。

while ([encodingTask isRunning]){ 
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 
    sleep(1); 
    [self encodeProgressTimer]; 
    [pool drain]; 
} 

その他のもの:あなたがスレッド上でこれを実行している場合、あなたは直接ユーザーインターフェイス項目を更新することはできません。実際にUIを更新するには、performSelectorOnMainThread:のようなものを使用する必要があります。これをスレッドで実行していない場合は、デザインを再考する必要があります。ループが実行されている間は、アプリケーションのUI全体がフリーズします。

+0

それはそれです!私がNSAutoReleasePoolを入れてもクラッシュしたとき、私はそれがまだメモリ管理上の問題であると仮定していました。私はまた、メインスレッドでステータスバーの更新を実行する必要がありました。すべてがスムーズに実行されているようです、ありがとうございます! – Kris

0

あなたは、参照からここにプロパティまたはnilを使用することをお勧めします。

if (statusTitle) { 
     [statusTitle release]; 
     statusTitle = nil; 
} 
関連する問題