views:

644

answers:

2

I decided to use the GC for memory management for my latest Cocoa project, and I discovered something interesting--if I create a brand new Cocoa app project in Xcode, turn GC to supported or required (I tried both), build, and run it it leaks, it shows memory leaks!

Mostly large numbers of tiny leaks of objects of type NSCFData, GeneralBlock, CGEvent, CFDictionary, CGSRegion, etc.

Steps to reproduce:

  1. File->new project->Cocoa app
  2. Project->Edit Project settings->GC Required (or supported, either one)
  3. Build->Build
  4. Run->Run with performance tool->Leaks
  5. Wait for leak detection to trigger (I have it set to 10 secs, it defaults to 30)

80% of the time or so I get a leak of around 2-20 Kb of various objects of the sort listed above.

Does anybody else have this same behavior?


EDIT: I tested the below circumstance by renaming the InputManagers folder (at which point the log messages went away, so they were definitely no longer being loaded) and am still getting the memory leaks. So it doesn't seem likely that had anything to do with it. I'm leaving the text there so Ashley Clark's answer still makes sense.

The only odd circumstance I know if is I'm getting the following message in the console any time I run an app with GC enabled:

2008-12-12 13:03:09.829 MemLeakTest[41819:813] Error loading /Library/InputManagers/Inquisitor/Inquisitor.bundle/Contents/MacOS/Inquisitor:  dlopen(/Library/InputManagers/Inquisitor/Inquisitor.bundle/Contents/MacOS/Inquisitor, 265): no suitable image found.  Did find:
    /Library/InputManagers/Inquisitor/Inquisitor.bundle/Contents/MacOS/Inquisitor: GC capability mismatch
2008-12-12 13:03:09.840 MemLeakTest[41819:813] Error loading /Library/InputManagers/Saft/SaftLoader.bundle/Contents/MacOS/SaftLoader:  dlopen(/Library/InputManagers/Saft/SaftLoader.bundle/Contents/MacOS/SaftLoader, 265): no suitable image found.  Did find:
    /Library/InputManagers/Saft/SaftLoader.bundle/Contents/MacOS/SaftLoader: GC capability mismatch

which I'm guessing has something to do with those two plug-ins trying to load into every single program that starts, not just Safari (which they're plug-ins for). I'm not sure if that has anything do do with this or not, but it definitely seems like a possibility. I don't have convenient access to a clean instead of OS X 10.5 with Dev tools to test whether or not this same thing happens on a virgin install without SAFT or Inquisitor.

+1  A: 

Those log messages are telling you that the Inquisitor.bundle and the SaftLoader.bundle are not built to run under GC programs and therefore are not being loaded. And while they may be meant only for Safari, they are input managers which means every Cocoa application tries to load them on startup, so an improperly written input manager can cause lots of problems.

I doubt they're responsible for what you're seeing but if you wanted to test without them just rename the InputManagers folder before you run your tests and they will be ignored.

Where are you seeing these leaks though?

Ashley Clark
I'm seeing the leaks in a completely stock Cocoa app. I go File->new project->Cocoa app, Project->Edit Project settings->GC Required (or supported, either one), Build->Build, Run->Run with performance tool->Leaks, and every 10 seconds I will almost always see a leak of 2-21 Kb or so
Lawrence Johnston
I do those same steps on mine and I don't see any leaks being reported. This is on 10.5.5 with Xcode 3.1.2. Perhaps you have an input manager that is being loaded besides Saft and Inquisitor? I'd move that folder out of the way and try again.
Ashley Clark
It seems the only way I can even show any leaks is to open the print dialog, but I know for a fact that my default printer driver has memory issues under GC so I think that is particular to my system.
Ashley Clark
Well, I just tried renaming the InputManagers folder but am still seeing the leaks, so something odd is up.
Lawrence Johnston
With even more testing I see that the "leaked" objects I'm seeing are getting reaped and reused as new objects as I generate new events. This might be helpful to realize while you examine your object graph.
Ashley Clark
+5  A: 

The leaks tool isn't accurate under Objective-C garbage collection in Leopard, because it doesn't know enough about the runtime structures of the garbage collector to actually determine what objects are still extant but ready to be reclaimed.

Also, you're a bit mistaken in your interpretation of the results of leaks: What look like leaks aren't coming from NSCFData, CGEvent, and so on — those are the supposed leaked objects.

The info gc-references and info gc-roots commands in GDB are what you'll want to use if you think specific objects are living too long under Objective-C garbage collection. Bill Bumgarner discusses them along with the general concept of "leaks" under GC in this post to Cocoa-Dev.

Chris Hanson
Thank you. As you can see I'm very new to using the Objective-C GC and am still trying to learn the ropes. So would it then be accurate to say that if I'm using the GC (and not CFRetain/CFReleasing anything) I can disregard leaks? How would I check for leaks on something CFRetain/Released?
Lawrence Johnston