我的macOS應用程序遭受嚴重的內存泄漏。經過大量調試後,我似乎找到了原因,但我仍然不太明白。macOS:由setNeedsDisplayInRect導致的內存消耗
該應用程序將像素繪製到內部緩衝區,然後實際將其繪製到NSView
子類的drawRect
方法中。重繪由[self setNeedsDisplayInRect:rect]
觸發。
幾個小時後,程序消耗了幾千兆字節的RAM。但是,當我把電話setNeedsDisplayInRect
放在一個循環中來調用它時,比如說每10,000次(而不是僅僅一次)重新繪製時,內存消耗在幾分鐘內就會上升到千兆字節。
爲了確保內存不在drawRect
方法中泄漏,我刪除了整個主體,只留下一個空方法。
據筆者所知,所有給予setNeedsDisplayInRect
的指令都被存儲起來,直到在下一輪事件循環中實際處理重繪爲止。所以當我稱它爲10,000次時,我預計內存消耗會更高,但我不希望它會一直保持上升 - 我預計在事件循環的一次迭代之後,所有存儲的rects將被清除。
那麼,爲什麼調用setNeedsDisplayInRect
時內存的數量會持續上升?我知道每秒鐘多次調用10000次並不是正常使用,但在正常情況下,內存使用量也會持續增長,但速度要慢很多。
代碼摘錄:
- (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];
}
}
這確實看起來是問題所在。奇怪的是,這沒有記錄在setNeedsDisplay *文檔中。我用'dispatch_async(dispatch_get_main_queue(),^(void){[self setNeedsDisplayInRect:rect];});' ...替換了'[self setNeedsDisplayInRect:rect]',現在內存不再泄漏。也就是說,它仍然緩慢上升,但一段時間後突然下降;重複。 – Mathijs