2017-02-16 8 views
0

私のmacOSアプリケーションは重大なメモリリークを被ります。私はまだそれを理解していないが、多くのデバッグの後、私は原因を見つけたようだ。macOS:setNeedsDisplayInRectによるメモリ消費

このアプリケーションはピクセルを内部バッファに描画します。このピクセルは、NSViewサブクラスのdrawRectメソッドで実際にスクリーンに描画されます。再ペイントは[self setNeedsDisplayInRect:rect]によってトリガされます。

数時間後、プログラムは数ギガバイトのRAMを消費します。しかし、私が再描画したいときに、setNeedsDisplayInRectという呼出しをループに入れて、言い換えると、1回だけではなく、1万回と言うと、メモリ消費は数分でギガバイトに上昇します。

メモリがdrawRectメソッドで漏れていないことを確認するために、完全なボディを削除して空のメソッドのみを残しました。

ドキュメントからわかるように、setNeedsDisplayInRectに与えられたすべての矩形は、再描画がイベントループの次の実行で実際に処理されるまで格納されます。だから私が10,000回呼び出すと、メモリ消費量はもっと高くなると予想されますが、それはいつも上昇し続けるとは思っていません。イベントループの1回の繰り返しの後に、格納されたすべてのrectをクリーンアップすると思います。

したがって、setNeedsDisplayInRectを呼び出すと、メモリの容量が増加し続けているのはなぜですか?私は10,000回それを1秒間に何度も呼び出すことを知っていますが、まったく通常の使用ではありませんが、メモリー使用量は通常の状況でも上昇し続けます。

コードの抜粋:あなたは二次/バックグラウンドスレッドからこれを呼び出している場合

- (void)drawRect:(NSRect)dirtyRect { 
// Currently, nothing happening 
} 

// My own method, that gets called from elsewhere. 
- (void) drawToScreen:(int) x : (int) y : (int)w :(int)h :(int *)data 
{  
    int rectYPos = MAX(height - y - h, 0); 
    NSRect rect = NSMakeRect(x, rectYPos, w, h); 
    for(int i = 0; i < 10000; i++) 
    { 
     [self setNeedsDisplayInRect:rect]; 
    } 
} 

答えて

1

は、あなたが(Appleのドキュメントから)確認したいかもしれません:

「もしアプリケーションのセカンダリスレッドビューの一部をメインスレッド上に再描画したい場合は、display、setNeedsDisplay :, setNeedsDisplayInRect :, setViewsNeedDisplay:などのメソッドを使用してはいけません。代わりに、メインスレッドにメッセージを送信するか、それらのメソッドを呼び出す必要があります代わりにperformSelectorOnMainThread:withObject:waitUntilDone:メソッドを使用してください。

https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html

+0

これは実際問題として発生しているようです。これはsetNeedsDisplay * docsには記載されていません。私は '{self setNeedsDisplayInRect:rect]'を 'dispatch_async(dispatch_get_main_queue()、^(void){[self setNeedsDisplayInRect:rect];});' ...に置き換え、メモリはもはやリークしません。つまり、それはまだゆっくりと上昇しますが、しばらくしてからは急に落ちます。繰り返す。 – Mathijs