STOP PRESS 好的,在您看到以下问题中的单词 retainCount
之前,请跳到底部的 EDIT 我已经声明我已经停止使用它了。
我的 Cocoa 应用程序,它使用 MRR ,在调用 NSApplicationMain()
之前,创建了许多全局资源,我在 main()
中加载这些资源。由于 NSApplicationMain()
没有返回,我使用 atexit()
Hook 了这些资源的清理,如下所示:
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);
但是 cleanup()
在我的 NSDocument
子类中的任何 View 被 dealloc
之前被调用(我缺少日志消息来显示这一点),因此全局资源中对象的引用计数有时是 > 1
。我过于谨慎并试图通过使用此方法释放我的全局资源来预防内存泄漏:
+ (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--;
}
}
我的日志显示如下:
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
我的问题(终于!)是:
有没有办法确保我在所有 NSDocument
实例都被销毁后清理我的全局资源并停止获得这些漏报?
编辑:我已经解除了 fullRelease
调用并且只是在我的资源上执行了正常的 release
并且 Instruments 没有检测到任何内存泄漏,所以一切正常,但我很好奇为什么 NSDocument
对象在调用 atexit()
之前似乎没有被释放。
最佳答案
不要发布不属于你的东西!
每个保留都属于其他人。仅向对象发送 release
以平衡对 new
、alloc
、copy
或 retain 的调用
(NARC。)这种行为将不可避免地导致生产代码崩溃。
您似乎想确保一个对象被释放,而不是简单地被处理。如果你拥有这个对象,就释放一次;对它的其他引用属于其他对象。您的代码中确实可能存在内存泄漏(我们无法仅从该代码示例中判断),但通常可以通过静态分析器、Instruments 和一些肘部润滑脂找到这些泄漏。
更重要的是:当您的进程退出时,操作系统会为您释放所有内存。这不是 C 标准的一部分,但它只是 OS X 和 iOS 的操作方式,也是支持 Objective-C 的其他平台上的预期行为。因此,当您的进程退出时,您不必做任何特殊的清理工作,除了可能将文件写入磁盘或类似的东西。事实上,许多 Cocoa 应用程序都懒得释放它们的应用程序委托(delegate)拥有的任何东西,因为让操作系统转储内存比调用 -release
更快> 在数以千计的物体上。
不要调用 -retainCount
!
它在撒谎。干净利落。它包括 Cocoa 使用的临时引用,最重要的是,您应该永远不要尝试干扰它们。 -retainCount
是一个有毒的符号。
关于objective-c - 清理App全局资源的最佳位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12121693/