2010-06-04 63 views
0

我有我有两种方法在不同的类。一个是类方法,另一个是实例方法。我从实例方法调用类方法。当实例方法完成时,会给运行时错误“EXC_BAD_ACCESS”。NSArray运行时数组

#import "xmlObject.h" 
#import "textmeAppDelegate.h" 
@implementation Class1 
    - (void)method1 { 
       textmeAppDelegate *del = (textmeAppDelegate *)[[UIApplication sharedApplication] delegate]; 

       NSArray *bgColor = [[NSArray alloc] initWithArray:[xmlObject fetchImmediateChildrenValues:[del.navigationbarStyle objectForKey:@"backgroundcolor"]]]; 
       UIColor *color = [UIColor colorWithRed:[[bgColor objectAtIndex:3] floatValue] green:[[bgColor objectAtIndex:2] floatValue] blue:[[bgColor objectAtIndex:1] floatValue] alpha:[[bgColor objectAtIndex:0] floatValue]]; 
       CGContextSetFillColor(context, CGColorGetComponents([color CGColor])); 
       CGContextFillRect(context, rect); 
       [bgColor release]; 

     } 
    @end 

@implementation xmlObject 
     + (NSArray *) fetchImmediateChildrenValues:(NSMutableDictionary *) node { 
     NSMutableDictionary *tmp = [[node objectForKey:@"children"] retain]; 
     NSArray *keys = [[NSArray alloc] initWithArray:[tmp allKeys]]; 
     keys = [keys sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; 
     NSMutableArray *pushArr = [[[NSMutableArray alloc] init] autorelease]; 
     NSString *val = [[NSString alloc] init]; 
     for(NSString *str in keys) { 
      val = (NSString *)[[tmp objectForKey:str] objectForKey:@"innertext"]; 
      [pushArr addObject:val]; 
     } 
     [val release]; 
     [keys release]; 

     return [NSArray arrayWithArray:pushArr]; 
     } 

@end 

代码有什么问题?同时也是应用崩溃的这行代码 应用程序崩溃,如果我加入这一行

NSArray *bgColor = [[NSArray alloc] initWithArray:[xmlObject fetchImmediateChildrenValues:[del.navigationbarStyle objectForKey:@"backgroundcolor"]]]; 

如果我删除应用程序运行速度流畅。

+0

'xmlObject'从哪里来? – d11wtq 2010-06-04 08:51:10

+0

此外,'textmeAppDelegate'是一个有效的类型?它看起来更像是一个实例变量的名称,而不是一个类型,但是您试图将它用作类型。 – d11wtq 2010-06-04 08:53:03

+0

xmlObject是在文件开始处导入的类。和textmeAppDelegate是一个有效的类型,因为它是我在我的应用程序的不同部分调用委托。 – 2010-06-04 09:49:37

回答

1

我对你的代码有几点评论。其中之一是你的崩溃的直接原因,但你至少还需要解决另一个问题。简短的答案是,你通过释放val和键。

NSArray *bgColor = [[NSArray alloc] initWithArray:[xmlObject fetchImmediateChildrenValues:[del.navigationbarStyle objectForKey:@"backgroundcolor"]]]; 

你并不需要在这里创建一个新的数组,你可以简单地写:

NSArray *bgColor = [xmlObject fetchImmediateChildrenValues:[del.navigationbarStyle objectForKey:@"backgroundcolor"]]; 

如果你这样做,你不需要[bgColor release]进一步下跌。

NSArray *keys = [[NSArray alloc] initWithArray:[tmp allKeys]]; 
keys = [keys sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; 

这两行泄漏第一个NSArray,你分配它,但你用排序后的版本直接覆盖它。事实上,你可以简单的写:

keys = [[tmp allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; 

注意,你没有自己的密钥,所以你可以摆脱[keys release]线的进一步下跌。

NSString *val = [[NSString alloc] init]; 
for(NSString *str in keys) { 
    val = (NSString *)[[tmp objectForKey:str] objectForKey:@"innertext"]; 
    [pushArr addObject:val]; 
} 
[val release]; 

这是您的直接问题的来源。你首先分配一个新的字符串。然后,在循环的每次迭代中立即覆盖它。所以分配的NSString泄漏。在每次迭代中,您都不拥有由[[tmp objectForKey:str] objectForKey:@"innertext"];返回的val,因此循环后的版本ov val不应该在那里。

在附注上,objectForKey:返回一个id - 对NSString *的转换是多余的。大多数人都把它排除在外。

  [keys release]; 

回到上面的位置,我告诉你,你正在泄漏你的分配键?那么你与你重写的新版本密钥并不拥有。因此你不能在这里释放密钥。

return [NSArray arrayWithArray:pushArr]; 

这很好。我的偏好是:

return [[pushArray copy] autorelease]; 

但它只是一个风格问题。你也可以返回pushArray,但pushArray是可变的,调用者可以依赖返回值是不可变的。

+0

感谢百万人的回复并感谢万亿人解决问题。这让我发疯。你能告诉我为什么在应用程序启动时,我在控制台上得到了很多'malloc:*** object error 0x43181e0:double free'的错误 – 2010-06-04 13:36:09

+0

很可能在代码的其他地方有很多类似的问题。我认为你需要回顾大部分内容。 – JeremyP 2010-06-04 15:31:35

+0

我回顾了我的应用程序,牢记上面的要点,现在只剩下几个漏洞。什么可能是从整个应用程序中删除泄漏的过程。 – 2010-06-05 09:42:24

1

用NSZombieEnabled设置测试你的代码...它应该给你足够的信息来解决你的问题。

+0

我启用了NSZombieEnabled。你能告诉我如何得到“EXC_BAD_ACCESS”运行时错误的原因 – 2010-06-04 10:12:56

+0

EXC_BAD_ACCESS通常意味着你正在发送消息给释放对象。 NSZombieEnabled将为每个释放对象放置一个虚拟对象,这将在释放后通过消息时通知您。 检查您的控制台日志... – Macmade 2010-06-04 10:16:23

+0

应用程序在开始时在控制台上崩溃 *** - [CFString发布]:发送到释放实例的消息0x43385f0 – 2010-06-04 10:38:33