tro*_*foe 2 macos objective-c nsdocument nsapplication-delegate
停止按下确定在您看到retainCount以下问题中的单词之前,请跳到底部的编辑,我已经说过我已经停止使用它.
我的Cocoa App使用MRRmain(),在NSApplicationMain()调用之前创建了许多全局资源,我正在加载它.由于NSApplicationMain()没有返回,我已经使用atexit()这样的方式来清理这些资源的清理:
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);
Run Code Online (Sandbox Code Playgroud)
然而cleanup(),在我的NSDocument子类中dealloc的任何视图都是'd(我缺少显示此消息的日志消息)之前调用它,因此有时候全局资源中的对象的引用计数> 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--;
}
}
Run Code Online (Sandbox Code Playgroud)
我的日志显示以下内容:
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
Run Code Online (Sandbox Code Playgroud)
我的问题(终于!)是:
有没有办法确保在所有NSDocument实例都被销毁后我清理我的全局资源并停止获取这些漏报?
编辑:我取消了fullRelease调用,只是release对我的资源执行了正常操作,仪器没有检测到任何内存泄漏,所以事情还可以,但我很好奇为什么这些NSDocument对象在atexit()被调用之前似乎没有被释放.
不要发布你不拥有的东西!
每个保留属于其他人.仅发送release到一个对象来平衡你的来电new,alloc,copy,或retain(NARC).这种行为将不可避免地导致生产代码崩溃.
看起来你想要确保一个对象被释放而不是简单地处理.如果您拥有该对象,请释放一次; 对它的其他引用属于其他对象.这是可能的,你就必须在你的代码的内存泄漏(我们不能从这个代码示例只是告诉),但这些通常可以用静态分析仪,仪器仪表,有点苦劳的发现.
更重要的是:当您的进程退出时,操作系统将为您释放所有内存.这不是C标准的一部分,但它只是OS X和iOS的运行方式,而且它是支持Objective-C的其他平台上的预期行为.因此,除了将文件写入磁盘或类似文件之外,您不必在进程退出时执行任何特殊操作.实际上,许多Cocoa应用程序都不愿意释放其app代理所拥有的任何内容,因为让操作系统转储内存比调用-release数千个对象更快.
别打电话-retainCount!
它的谎言.干净利落.它包括Cocoa使用的临时引用,最重要的是,你永远不应该试图干扰它们.-retainCount是一个有毒的象征.
一些说明:
不要使用retainCount; 有关详细信息,请参阅http://whentouseretaincount.com上的链接
atexit()处理程序在高级编程中没用.调用时,应用程序处于相对未定义的状态.框架将拆除一些东西,但正如你所指出的,将会有大量的对象永远不会被释放.在某些情况下,可能根本不会调用atexit().
您不能依赖应用程序终止来执行任何类型的必需状态清理.用户可能会强行退出您的应用.系统也可能或者强制重启.应将终止行为视为优化; 你可以做一些能让下一次发射更快的东西.
在应用程序终止期间,无需释放任何内容.无论应用程序状态如何,系统都会在终止时回收所有应用程序资源.换句话说,在终止时留在内存中的对象不是泄漏.
通常,"泄漏"检测工具只能用于解决明显的问题.泄漏仅检测内存泄漏.它无法检测内存增加,其中对象累积仍然以某种方式连接到全局.吸收不是技术上的泄漏,但它们很容易成为问题的重要来源.
HeapShot分析将检测泄漏和内存增加.
考虑迁移您的应用以使用ARC.ARC的指导模式之一是编译器完全了解对象的生命周期.ARC下不允许表达模糊不清的表达(在某些情况下没有适当的标记).同样,ARC编译器和分析器可以对您的代码进行更深入的分析,发现许多可能非常微妙的问题.