我在应用程序的几个地方使用单例模式,并且clang
在分析代码时出现内存泄漏错误.
static MyClass *_sharedMyClass; + (MyClass *)sharedMyClass { @synchronized(self) { if (_sharedMyClass == nil) [[self alloc] init]; } return _sharedMyClass; } // clang error: Object allocated on line 5 is no longer referenced after this point and has a retain count of +1 (object leaked)
我正在使用这些设置scan-build
:
scan-build -v -v -v -V -k xcodebuild
我非常肯定单例中的代码很好 - 毕竟,它与Stack Overflow以及Apple的文档中引用的代码相同 - 但我希望将内存泄漏警告整理出来以便我的扫描 - 建立回报成功.
我可能会异常密集,但肯定是你的第5行
[[self alloc] init];
分配一个包含类类型的对象,并迅速抛弃它?你不想要吗?
_sharedMyClass = [[self alloc] init];
?
Apple已经更新了推荐的单例代码以通过静态分析器:
+ (MyGizmoClass*)sharedManager { if (sharedGizmoManager == nil) { sharedGizmoManager = [[super allocWithZone:NULL] init]; } return sharedGizmoManager; } + (id)allocWithZone:(NSZone *)zone { return [[self sharedManager] retain]; }
现在+sharedManager
调用super -allocWithZone:
并分配返回值-init
,而singleton -allocWithZone:
只返回一个保留的sharedInstance.
编辑:
为什么保留+ allocWithZone:?
+ allocWithZone:被覆盖,因为使用MyGizmoClass的人可以通过调用[[MyGizmoClass alloc] init]而不是[MyGizmoClass sharedManager]来绕过单例.它被保留,因为+ alloc应该始终返回一个保留计数为+1的对象.
每次对+ alloc的调用都应该与-release或-autorelease进行平衡,因此如果没有在+ allocWithZone:中保留,共享实例可能会从其他用户下解除分配.