NSTableView reloadData leaking memory

╄→尐↘猪︶ㄣ 提交于 2019-12-12 04:42:01

问题


I've been checking my application for leaks using the Instruments application. Under a certain set of circumstances a table view in a HUD Panel is being updated once a second. It is all working fine except every second (reloadData) the number of _NSArrayl objects increases by one. If I change my datasource to just a return(@""); (they are all text cells) then the problem stays (no change). If I remove all my surrounding code to just:

[myTableView reloadData];

and

- (id)tableView:(NSTableView *)tv objectValueForTableColumn:(NSTableColumn *)column row:(int)rowIndex {
   return(@"");
}

(or even returning nil)

problem persists. Comment out the [myTableView reloadData] and problem goes away. Each block is an _NSarrayl and is 32 bytes in size, and the detail:

   0 libsystem_c.dylib calloc
   1 libobjc.A.dylib class_createInstance
   2 CoreFoundation __CFAllocateObject2
   3 CoreFoundation +[__NSArrayI __new::]
   4 CoreFoundation -[__NSPlaceholderArray initWithObjects:count:]
   5 CoreFoundation +[NSArray arrayWithObjects:]
   6 AppKit -[NSWindow _runLoopModesForInvalidCursorRectsObserver]
   7 AppKit __-[NSWindow _postInvalidCursorRects]_block_invoke_1
   8 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__
   9 CoreFoundation __CFRunLoopDoObservers
  10 CoreFoundation __CFRunLoopRun
  11 CoreFoundation CFRunLoopRunSpecific
  12 HIToolbox RunCurrentEventLoopInMode
  13 HIToolbox ReceiveNextEventCommon
  14 HIToolbox BlockUntilNextEventMatchingListInMode
  15 AppKit _DPSNextEvent
  16 AppKit -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]
  17 AppKit -[NSApplication run]
  18 AppKit NSApplicationMain

I have noticed in the history for these objects there is an Autorelease entry so I do wonder if it has been autoreleased (retain count is still 1). But after 5 mins+, nothing has released them so maybe the autorelease pool is not being released. I do not create any autorelease pools (and don't release any), leaving that the application framework. Should I be doing something with the autorelease pools ?

#   Address Category    Event Type  RefCt   Timestamp   Size    Responsible Library Responsible Caller
0   0x100669cf0 __NSArrayI  Malloc  1   00:01.342.634   32  AppKit  -[NSWindow _runLoopModesForInvalidCursorRectsObserver]
1   0x100669cf0 __NSArrayI  Autorelease <null>  00:01.342.636   0   AppKit  -[NSWindow _runLoopModesForInvalidCursorRectsObserver]

Any suggestions as to what I might be doing incorrectly will be very appreciated.

Note that the circumstances of 1 second updates is not a "normal situation" for the application but it can happen and then application is designed for a long time; i.e. not an application your run, exit, run again, exit, etc.

They are not being detected as "leaks" but the allocation count keeps increasing for ever so I assume they are leaks in practice (or something is going wrong)

I'm NOT using ARC not "Garbage Collection" - just the retain/release system and I'm tend to use retain/release and my own code only uses autorelease occasionally and nowhere to do with this code.

Additional Info: I have been sitting watching the count increase, only using the Instruments application (the tableview is in a HUD that is always visible). However, if I e.g. move the mouse over the "leaky" tableview - the count goes back down to something reasonable. Move the HUD window containing the tableview on the screen a bit and the count goes back down, etc. It seems to be the lack of user activity that is allowing this to happen. I'm still stumped but thought this new observation might help with ideas (or if anybody tried to reproduce it).


回答1:


The code itself does not leak. But what might happen is that the outter autorelease pool is not drained. This is a tricky thing in AppKit: AppKit run loop adds an autorelease pool automatically but only drains it when it receives events (i.e. you move the mouse).

You can confirm that by activating the app and just moving the mouse then trying leaks again.

This means that, in general, it's a good idea to add your own autorelease pool in your custom non-event-driven callbacks. Some basic Foundation mechanism already do that for you (e.g. NSTimer creates a pool for you before firing and drains it after) but not everything do it for you.

In this particular case, it seems that you don't have much control over that particular callback so:

1) think about tickling your application before running leaks

2) maybe file a bug to Apple




回答2:


Update and subsequent question (sorry) ** Following your advice, I have added a bit below the [myTableView reloadData] to post a dummy/harmless message to the Application (looked safer than posting directly to the window concerned).

NSEvent *dummyEvent=[NSEvent mouseEventWithType:NSMouseMoved location:NSMakePoint(0.0,0.0) modifierFlags:0 timestamp:0.0 windowNumber:0 context:nil eventNumber:0 clickCount:0 pressure:0.0];
[NSApp postEvent:dummyEvent atStart:FALSE];

My idea was to add something that will happen after the table view has cone everything (basically when the event queue becomes empty. that will look like the user doing something. It seems to work in so far as the ever increasing allocation count no longer increases (moves around a bit as expected but is basically stable).

However, I have not done much with events and am concerned that my "dummyEvent" might not be harmless or might start causing problems in future. Is there a better way to achieve this or is there a better event (or parameters) I should use ?

I did try

NSEvent *dummyEvent=[NSEvent otherEventWithType:NSApplicationDefined location:NSMakePoint(0.0,0.0) modifierFlags:0 timestamp:0.0 windowNumber:0 context:nil subtype:(short)(0) data1:0 data2:0];

but I am less confidant in this as I have no custom event handlers and am unsure where it might end-up. Plus I also got an address violation 1st time with this variant - but I wonder if that is something else as it is has not happened again. I can see how a dummy mouse move would be harmless as long as none of my parameters would cause a crash/assertion failure or similar.



来源:https://stackoverflow.com/questions/11874726/nstableview-reloaddata-leaking-memory

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!