【问题标题】:NSXMLParser throwing off EXC_BAD_ACCESS when ARC enabled启用 ARC 时 NSXMLParser 抛出 EXC_BAD_ACCESS
【发布时间】:2013-02-04 07:14:39
【问题描述】:

iOS 初学者在这里。我正在尝试为新闻网站创建一个 RSS 阅读器,RSS 解析器处于正常工作状态,但如果在启用 ARC 的情况下编译,它会给出异常 EXC_BAD_ACCESS (code=2 address=0xc)。

这是我调用解析器的方式:(在我的视图控制器中)

NSMutableArray* articleListMainPage;

- (void)viewDidLoad
{
    NSURL *mainFeed = [[NSURL alloc]initWithString:@"http://my.domain.com/rss.xml"];
    NSXMLParser *nsXmlParser = [[NSXMLParser alloc] initWithContentsOfURL:mainFeed];
    NewsParser *myparser = [[NewsParser alloc] initNewsParser];
    [nsXmlParser setDelegate:myparser];

    if ([nsXmlParser parse]) {
        NSLog(@"Parsed article count : %i", [myparser.articles count]);
        articleListMainPage = [myparser.articles copy];
    } else {
        NSLog(@"Error parsing document!");
    }
    nsXmlParser = nil;
    mainFeed = nil;
    myparser = nil; // This line throws the exception.

    [super viewDidLoad];
}

这是解析器本身:

// NewsParser.m
#import "NewsParser.h"
#import "RSSEntry.h"

@implementation NewsParser

@synthesize article, articles, currValue;

- (NewsParser *) initNewsParser
{
    if (self = [super init]) return self; else return nil;
}

- (void)parser:(NSXMLParser *)parser
    didStartElement:(NSString *)elementName
    namespaceURI:(NSString *)namespaceURI
    qualifiedName:(NSString *)qualifiedName
    attributes:(NSDictionary *)attributeDict {

    if ([elementName isEqualToString:@"channel"]) {
        self.articles = [[NSMutableArray alloc] init];
    }
    if ([elementName isEqualToString:@"item"]) {
        self.article = [[ArticleEntry alloc] init];
    }
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    if (!currValue) {
        self.currValue = [[NSMutableString alloc] initWithString:string];
    } else {
        [self.currValue appendString:string];
    }
}

- (void)parser:(NSXMLParser *)parser
    didEndElement:(NSString *)elementName
     namespaceURI:(NSString *)namespaceURI
    qualifiedName:(NSString *)qName {

    if ([elementName isEqualToString:@"channel"]) {
        return;
    }

    if ([elementName isEqualToString:@"item"]) {
        [self.articles addObject:self.article];
        self.article = nil;
    } else {
        if ([[NSArray arrayWithObjects:@"title",@"link",@"description",nil] containsObject:elementName])
             [self.article setValue:self.currValue forKey:elementName];
    }
    self.currValue = nil;
}

@end

//NewsParser.h

#import <Foundation/Foundation.h>
#import "RSSEntry.h"

@interface NewsParser : NSXMLParser <NSXMLParserDelegate> {
    NSMutableString *currValue;
    NSMutableArray *articles;
    ArticleEntry *article;
}
- (NewsParser *) initNewsParser;
@property (nonatomic,retain) ArticleEntry *article;
@property (nonatomic,retain) NSMutableArray *articles;
@property (nonatomic,retain) NSMutableString *currValue;
@end

.. 以及我用于存储 RSS 条目的类。

//RSSEntry.h
#import <Foundation/Foundation.h>

@interface ArticleEntry : NSObject {
    NSString *title;
    NSString *link;
    NSString *description;
}

@property (nonatomic, retain) NSString *title;
@property (nonatomic, retain) NSString *link;
@property (nonatomic, retain) NSString *description;

- (id)initNewArticle:(NSString*)_title url:(NSString*)_link description:(NSString*)_desc;

@end

//RSSEntry.m

#import "RSSEntry.h"

@implementation ArticleEntry
@synthesize title,link,description;
- (id)initNewArticle:(NSString *)_title url:(NSString *)_link description:(NSString *)_desc
{
    if ((self = [super init])) {
        title = [_title copy];
        link = [_link copy];
        description = [_desc copy];
        return self;
    }
    else return nil;
}
@end

就像我说的,没有 ARC 也能正常工作,但我想知道我是否在做一些我不应该做的事情(例如,保留一些我不应该做的事情,或者没有正确地释放一些东西/过度释放一些东西)代码。

感谢您的宝贵时间..

【问题讨论】:

  • 您是否尝试过对您的代码运行“分析”?转到 Xcode 中的“Product -> Analyse” :) 它会为您找到内存问题。
  • 请发布堆栈跟踪。
  • 嗨,正如 Cupcake 所说,运行分析器。我只是给你一个初步的回顾,你这里有内存泄漏: if ([elementName isEqualToString:@"channel"]) { self.articles = [[NSMutableArray alloc] init]; } if ([elementName isEqualToString:@"item"]) { self.article = [[ArticleEntry alloc] init]; }
  • postimage.org/image/72ffqjjnz 和分析什么也没给我..
  • DarthMike,在将 articles 添加到 articles 数组后,我将它们归零,在我处理完它们后它们不会被垃圾回收吗?

标签: ios objective-c automatic-ref-counting nsxmlparser


【解决方案1】:

所以这里的一个问题是您将 NewsParser 声明为 NSXMLParser 的子类,但它不应该是。它应该是 NSObject 的子类(或其他适当的东西)

所以在 NewsParser.h 中,试试这个:

@interface NewsParser : NSObject <NSXMLParserDelegate>

顺便说一句,如果没有 ARC,您确实存在内存泄漏。如果您打算在没有 ARC 的情况下再次编译此代码,分析器可以帮助您解决这些问题。不管有没有 ARC,这里都没有垃圾收集器(听起来好像你在指望一个?)

【讨论】:

  • 好吧,解决了它。我不明白 NewsParser 作为 NSXMLParser 的子类是如何导致它崩溃的,但我会接受它。
  • 我不知道如何使用分析器修复内存泄漏,我使用它时只收到“分析成功”的消息,没有其他反应。
  • 必须自己在 LLDB 中看到它,但是您没有为超类调用指定的初始化程序,导致超类的 dealloc 失败。无论如何,在大多数情况下,您没有理由继承 NSXMLParser。委托模式是正确的选择。
  • 如果您关闭 ARC,您可以使用静态分析器来指导您修复内存错误。或者只使用 ARC,这是更好的选择。希望对您有所帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-16
  • 1970-01-01
  • 2014-10-29
相关资源
最近更新 更多