STOP PRESS OK before you see the word retainCount
in the following question, please skip to the EDIT at the bottom where I have stated that I have stopped using it.
My Cocoa App, which uses MRR, creates many global resources, which I am loading in main()
, before NSApplicationMain()
is called. As NSApplicationMain()
doesn't return, I have hooked the clean-up of these resources using atexit()
, like this:
atexit(cleanup);
if (![CocoaUtil initCocoaUtil] ||
![PreferenceController initPreferenceController] ||
![ResourceManager initResourceManager])
{
criticalAlertPanel(@"Failed to initialize application",
@"Failed to initialize application");
return 4;
}
retval = NSApplicationMain(argc, (const char **)argv);
However cleanup()
is getting called before any of the views in my NSDocument
subclass are dealloc
'd (I have lack of log message to show this) and hence the reference counts of the objects in the global resources is sometimes > 1
. I am being over-cautious and attempting to pre-empt memory leaks by using this method to release my global resources:
+ (void)fullRelease:(id)obj
format:(NSString *)format, ...
{
if (obj == nil)
return;
NSUInteger retainCount = [obj retainCount];
if (retainCount > 1)
{
va_list va;
va_start(va, format);
NSString *objDesc = [[NSString alloc] initWithFormat:format arguments:va];
logwrn(@"%@ has a reference count of %lu", objDesc, retainCount);
[objDesc release];
}
while (retainCount > 0)
{
[obj release];
retainCount--;
}
}
My log shows the following:
12:15:04.954 INF -[AppController applicationDidFinishLaunching:] Application launched
12:15:06.702 INF -[AppController applicationShouldTerminate:] Application terminating
12:15:06.703 INF -[AppController applicationWillTerminate:] Application terminating
12:15:06.705 DBG cleanup Cleaning-up
12:15:06.705 INF +[ResourceManager finiResourceManager] Cleaning up
12:15:06.709 WRN +[CocoaUtil fullRelease:format:] _images[2] has a reference count of 2
12:15:06.709 WRN +[CocoaUtil fullRelease:format:] _images[3] has a reference count of 2
12:15:06.709 WRN +[CocoaUtil fullRelease:format:] _images[4] has a reference count of 2
12:15:06.710 WRN +[CocoaUtil fullRelease:format:] _images[5] has a reference count of 2
12:15:06.710 WRN +[CocoaUtil fullRelease:format:] _images[6] has a reference count of 2
12:15:06.710 WRN +[CocoaUtil fullRelease:format:] _images[7] has a reference count of 2
12:15:06.711 WRN +[CocoaUtil fullRelease:format:] _images[8] has a reference count of 2
12:15:06.711 WRN +[CocoaUtil fullRelease:format:] _images[9] has a reference count of 2
12:15:06.721 DBG +[PreferenceController finiPreferenceController] Cleaning up
12:15:06.721 DBG +[CocoaUtil finiCocoaUtil] Cleaning up
My question (finally!) is:
Is there a way to ensure I clean-up my global resource after all the NSDocument
instances have been destroyed and stop getting these false negatives?
EDIT: I have unhooked the fullRelease
call and just performed a normal release
on my resources and Instruments did not detect any memory leaks, so things are OK, but I am curious as to why the NSDocument
objects don't appear to be being released before atexit()
is called.