[CFDictionary objectForKey:]:发送到解除分配的实例的消息

时间:2011-09-12 17:44:17

标签: objective-c singleton nsdictionary nsmutabledictionary memory-management

在没有任何见解的情况下搜索网页后,我决定在此发布我的问题,希望有人可以解释下面的代码有什么问题。我只是无法在Objective-C中实现单例设计模式。我发现了一些在互联网上实现模式的代码,并对其进行了一些修改以添加从plist文件启动的字典(其中属性列表中的每个条目本身都是字典):

@interface UnitManager : NSObject {
NSString *someProperty;
NSDictionary *factors;
}

@property (nonatomic, retain) NSString *someProperty;
@property (nonatomic, retain) NSDictionary *factors;

+ (id) sharedUnitManager;

@end

// implementation file
#import "Unit.h"

#define MARGIN 20

static UnitManager *unitManager = nil;

@implementation UnitManager

@synthesize someProperty;
@synthesize factors;

#pragma mark Singleton Methods

+ (id)sharedUnitManager {
    @synchronized(self) {
        if(unitManager == nil)
            unitManager = [[super allocWithZone:NULL] init];
    }
    return unitManager;
}
+ (id)allocWithZone:(NSZone *)zone {
    return [[self sharedUnitManager] retain];
}
- (id)copyWithZone:(NSZone *)zone {
    return self;
}
- (id)retain {
   return self;
}
- (unsigned)retainCount {
    return UINT_MAX; //denotes an object that cannot be released
}
- (void)release {
    // never release
}
- (id)autorelease {
    return self;
}
- (id)init {
    if (self = [super init]) {
         someProperty = [[NSString alloc] initWithString:@"Default Property Value"];

        // get path to file that stores category order
        NSString *path = [[NSBundle mainBundle] pathForResource:@"factors" ofType:@"plist"];

        factors = [NSDictionary dictionaryWithContentsOfFile:path];


    }
    return self;
}
- (void)dealloc {
    // Should never be called, but just here for clarity really.
    [someProperty release];
    NSLog(@"should NEVER GET HERE!");
    [factors release];
    [super dealloc];
}

@end

然后,一些代码后来我尝试访问singleton对象中的字典,并且第一次调用它工作正常,但第二次访问deallocated内存!

- (void) someFunction {
...

    NSString *str = [[[[UnitManager sharedUnitManager] factors] objectForKey:category] objectForKey:name];
...
...



}

我得到的信息是

2011-09-12 17:39:44.567测试[7837:b603] - [CFDictionary objectForKey:]:发送到解除分配的实例0x4d565e0的消息< / EM> *

记忆痕迹:

(gdb)info malloc-history 0x5c73300 Alloc:块地址:0x05c73300长度:48 Stack - pthread:0xac2bd2c0帧数:44

0. 0x92573993 in malloc_zone_malloc
1. 0xebe87d in _CFRuntimeCreateInstance
2. 0xebe47a in CFBasicHashCreate
3. 0xf81e44 in __CFDictionaryCreateTransfer
4. 0xeed3ff in __CFBinaryPlistCreateObject2
5. 0xee2009 in __CFTryParseBinaryPlist
6. 0xee1a48 in _CFPropertyListCreateWithData
7. 0xee19ba in CFPropertyListCreateWithData
8. 0xee194f in CFPropertyListCreateFromXMLData
9. 0x791e34 in _NSParseObjectFromASCIIPropertyListOrSerialization
10. 0x7913d5 in +[NSDictionary(NSDictionary) newWithContentsOf:immutable:]
11. 0xf067bf in -[__NSPlaceholderDictionary initWithContentsOfFile:]
12. 0x791308 in +[NSDictionary(NSDictionary) dictionaryWithContentsOfFile:]
13. 0xcb38 in -[UnitManager init] at Unit.m:54
14. 0xc833 in +[UnitManager sharedUnitManager] at Unit.m:25
15. 0xe03a in -[Unit factor] at Unit.m:226
16. 0x39c9 in -[MainViewController updateTextFields] at MainViewController.m:113
17. 0x4037 in -[MainViewController refresh] at MainViewController.m:229
18. 0x79c669 in _nsnote_callback
19. 0xf879f9 in __CFXNotificationPost_old
20. 0xf0693a in _CFXNotificationPostNotification
21. 0x79220e in -[NSNotificationCenter postNotificationName:object:userInfo:]
22. 0x79e551 in -[NSNotificationCenter postNotificationName:object:]
23. 0x62f7 in -[MainViewController changeUnit:] at MainViewController.m:447
24. 0x2a4fd in -[UIApplication sendAction:to:from:forEvent:]
25. 0xba799 in -[UIControl sendAction:to:forEvent:]
26. 0xbcc2b in -[UIControl(Internal) _sendActionsForEvents:withEvent:]
27. 0xba750 in -[UIControl sendActionsForControlEvents:]
28. 0xfa59b in -[UISegmentedControl setSelectedSegmentIndex:]
29. 0xff39d in -[UISegmentedControl touchesBegan:withEvent:]
30. 0x4ed41 in -[UIWindow _sendTouchesForEvent:]
31. 0x2fc37 in -[UIApplication sendEvent:]
32. 0x34f2e in _UIApplicationHandleEvent
33. 0x11e8992 in PurpleEventCallback
34. 0xf90944 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__
35. 0xef0cf7 in __CFRunLoopDoSource1
36. 0xeedf83 in __CFRunLoopRun
37. 0xeed840 in CFRunLoopRunSpecific
38. 0xeed761 in CFRunLoopRunInMode
39. 0x11e71c4 in GSEventRunModal
40. 0x11e7289 in GSEventRun
41. 0x38c93 in UIApplicationMain
42. 0x2639 in main at main.m:14
43. 0x25b5 in start

有人可以解释这里发生了什么吗?我真的不明白为什么第二次我无法访问字典。我第二次使用它时没有看到任何解除分配字典的内容。

谢谢大家,

AA

1 个答案:

答案 0 :(得分:5)

    factors = [NSDictionary dictionaryWithContentsOfFile:path];

您正在为自动释放的对象设置实例变量。一旦消息池耗尽,下一封到factors的消息可能会 BOOM

该方法遵循框架API中每个方法的标准规则。请参阅policies guide

文档不遗余力地不按每个方法重复通用规则;即如果您没有阅读指南,您将无法理解每种方法必然如何运作。

这是一个“给人一条鱼,他会吃一天......教一个人钓鱼,他会养活自己一辈子”的方法。