静态NSMutableDictionary“只是泄漏”

时间:2012-04-20 18:45:59

标签: objective-c ios xcode macos

这是一个简单的课程:

#import "One.h"
#import "Two.h"

@implementation DataFileRegistrar

static NSMutableDictionary *elementToClassMapping;

+ (void)load
{
    [self registerClass:[One class] forElement:@"one"];
    [self registerClass:[Two class] forElement:@"two"];
}

+ (void)registerClass:(Class)class forElement:(NSString *)element
{
    if (!elementToClassMapping) {
        elementToClassMapping = [NSMutableDictionary dictionaryWithObject:class forKey:element];
    } else {
        [elementToClassMapping setValue:class forKey:element];
    }
}

+ (id)classForElement:(NSString *)element
{
    return [elementToClassMapping valueForKey:element];
}

@end

问题是这个编译器消息:

objc[7172]: Object 0x6840720 of class __NSCFDictionary autoreleased with no pool in place - just leaking - break on objc_autoreleaseNoPool() to debug

任何想法发生了什么?

基本上,我想要一个带有几个类方法和一个静态字典的简单类。它总是在没有实例化的情况下使用。我想在应用程序启动后立即将它用于一些事情,然后我想释放它的内存。我以为ARC可以解决这个问题。

3 个答案:

答案 0 :(得分:5)

您不应在静态变量上使用自动释放的对象。

更改行......

 elementToClassMapping = [NSMutableDictionary dictionaryWithObject:class forKey:element];

 elementToClassMapping = [[NSMutableDictionary alloc] initWithObjects:[NSArray arrayWithObject:class] forKeys:[NSArray arrayWithObject:element]];

如果没有创建自动释放池,也不要从第二个线程调用+ (void)registerClass:(Class)class forElement:(NSString *)element

答案 1 :(得分:4)

您的班级“+load正在调用调用autorelease的方法。

您的课程已在main之前加载。

您可以在+load中明确创建自动释放池:

+ (void)load
{
    @autoreleasepool {
        [self registerClass:[One class] forElement:@"one"];
        [self registerClass:[Two class] forElement:@"two"];
    }
}

但是,在main中创建任何线程之前,通常最好保证程序的初始化和加载顺序:

int main(int argc, const char * argv[]) {
  @autoreleasepool {
      [DataFileRegistrar initializeStaticStuff];
      ...

答案 2 :(得分:-1)

你在做什么就是把字典放在堆栈上(坦率地说是愚蠢的,因为你有很多方法不这样做)并且它会泄漏,因为它永远不会从堆栈中释放出来。

创建NSDictionary是为了与自动释放池一起使用(是的..我知道有些情况下使用静态的更好但是这些情况非常罕见)

在界面中声明NSMutableDictionary *elementToClassMapping;,一切都会正常工作