Objective-C Singletons和LLVM/clang泄漏警告

pix*_*x0r 2 objective-c llvm clang

我在应用程序的几个地方使用单例模式,并且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)
Run Code Online (Sandbox Code Playgroud)

我正在使用这些设置scan-build:

scan-build -v -v -v -V -k xcodebuild

我非常肯定单例中的代码很好 - 毕竟,它与Stack Overflow以及Apple的文档中引用的代码相同 - 但我希望将内存泄漏警告整理出来以便我的扫描 - 建立回报成功.

Ada*_*ght 6

我可能会异常密集,但肯定是你的第5行

[[self alloc] init];
Run Code Online (Sandbox Code Playgroud)

分配一个包含类类型的对象,并迅速抛弃它?你不想要吗?

_sharedMyClass = [[self alloc] init];
Run Code Online (Sandbox Code Playgroud)

  • 然后我猜想CLANG不够聪明,不能推断[self alloc]返回实际上是设置self参数,它将由init方法保存.因此它认为它只是丢失了(正如我所做的那样,没有更多的背景). (2认同)

Jus*_*son 5

Apple已经更新了推荐的单例代码以通过静态分析器:

+ (MyGizmoClass*)sharedManager
{
    if (sharedGizmoManager == nil) {
        sharedGizmoManager = [[super allocWithZone:NULL] init];
    }
    return sharedGizmoManager;
}

+ (id)allocWithZone:(NSZone *)zone
{
    return [[self sharedManager] retain];
}
Run Code Online (Sandbox Code Playgroud)

现在+sharedManager调用super -allocWithZone:并分配返回值-init,而singleton -allocWithZone:只返回一个保留的sharedInstance.

编辑:

为什么保留+ allocWithZone:?

+ allocWithZone:被覆盖,因为使用MyGizmoClass的人可以通过调用[[MyGizmoClass alloc] init]而不是[MyGizmoClass sharedManager]来绕过单例.它被保留,因为+ alloc应该始终返回一个保留计数为+1的对象.

每次对+ alloc的调用都应该与-release或-autorelease进行平衡,因此如果没有在+ allocWithZone:中保留,共享实例可能会从其他用户下解除分配.