简体   繁体   English

Objective-C内存管理:BAD_ACCESS错误

[英]Objective-C memory management: BAD_ACCESS error

I'm working on a bible iPhone app. 我正在开发一个圣经iPhone应用程序。 Here are the basics of what I'm doing so far: 这是到目前为止我正在做的基本工作:

  • My XMLParser parses an xml file and creates a Bible object 我的XMLParser解析一个xml文件并创建一个Bible对象

  • Specifically, the xml is stored in each Chapter object. 具体来说,xml存储在每个Chapter对象中。

  • Once parsing is done, the viewController grabs a Chapter from the Bible and displays its innerHtml in a UIWebview. 解析完成后,viewController从圣经中获取一章,并在UIWebview中显示其innerHtml。

This works, but whenever I try to access the Bible object outside of -(void)viewDidLoad; 这是可行的,但是每当我尝试在-(void)viewDidLoad;之外访问Bible对象时,就可以使用它。 it either gives me a BAD_ACCESS error, or the results for what I'm asking for is unreadable. 它要么给我一个BAD_ACCESS错误,要么是我要查询的结果不可读。 I think this is a memory management problem.. 我认为这是内存管理问题。

Here's what I'm doing in the viewController 这是我在viewController中所做的

- (void)viewDidLoad
{
    [super viewDidLoad];

    //Create parser and XML data object.
    //Then, parse that data

    finalBible = [[Bible alloc]init]; 

    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"KJV" ofType:@"html"];
    NSData *myData = [NSData dataWithContentsOfFile:filePath];

    //INT I WANTED TO USE TO ITERATE WHEN BUTTON WAS PRESSED TO ADVANCE TO NXT CHAPTER
    chapToShow = 2;

    parser = [[XMLParser alloc] init];
    nsParser = [[NSXMLParser alloc] initWithData:myData];

    //set delegate for NSXMLParser
    [nsParser setDelegate:parser];

    //PARSE THE XML FILE AND BUILD BIBLE OBJECT - PARSED OK!!
    if ([nsParser parse]) {
        NSLog(@"Parsed with no errors!! :)");
    }else{
        NSLog(@"Error parsing document");
    }

    //IT SEEMS MY PROBLEMS MAY BE IN THIS TRADE OFF.
    //I WANT TO STORE THE PARSER'S BIBLE IN THIS NEW BIBLE OBJECT.
    finalBible = [parser getBible];

    //Test querying bible via pullVerse method - IT WORKS!!
    NSLog(@"%@",[finalBible pullVerse:@"65.021.000"]);


    NSString *firstChap = [[[[finalBible getTestament:0]getBook:@"Genesis"]getChapterWithInt:3]getInnerHtml];

    //Try and load Genesis 1 - THIS WORKS!!
    NSLog(@"...Loading Genesis 1...");
    [bibleView loadHTMLString:firstChap baseURL:nil];

    //LOADING THE VERSION WORKS HERE!!
    NSLog(@"Version = %@", [finalBible getVersion]);

}

- (IBAction)buttonPressed:(id)sender {
    NSLog(@"Now reading chapter %d", chapToShow);

    //HERE I'M TRYING TO GET THE BIBLE VERSION BUT THE APP CRASHES AS A RESULT
    NSLog(@"Testing the bible: Version = %@ \n OK", [finalBible getVersion]);

    //NOTE: I've even tried [[parser getBible] getVersion] and it still doesn't work.
    // I don't release the parser till the view's dealloc method, so I'm not sure why I            
    // can't access it here...

}

Of course, I'd be happy to post any other code. 当然,我很乐意发布任何其他代码。 I just didn't want to over-stuff the page with code, so I pasted only where I think the problem lies, or at least where it's occurring. 我只是不想用代码过度填充页面,所以只粘贴了我认为问题所在的位置,或者至少将其粘贴到了发生的位置。

You allocate finalBible, but then you set finalBible = [parser getBible] so the previous allocation is pointless. 您分配了finalBible,但随后设置了finalBible = [parser getBible]因此先前的分配毫无意义。 Also, it appears as though [parser getBible] returns an autoreleased object, so you should call [[parser getBible] retain] to make sure it does not leave memory. 另外,似乎[parser getBible]返回一个自动释放的对象,因此您应该调用[[parser getBible] retain]以确保它不会留下内存。

This is exactly what you need to do in your .h file add this line: 这正是您需要在.h文件中执行的操作,添加以下行:

@property(nonatomic, retain) Bible finalBible;

Then in your .m file add this line at the top: 然后在您的.m文件中,在顶部添加以下行:

//This generates the methods (get, set) for your instance variable
@synthesize finalBible;

Then drop this line: 然后放下这一行:

finalBible = [[Bible] alloc]init];

This is because if you keep it, there will be a memory leak right here: 这是因为,如果您保留它,这里将发生内存泄漏:

finalBible = [parser getBible];

Because now you are pointing to a new memory location, and the previous memory location had an object with a retain count of 1 provided by alloc init, and since there will no longer be any reference to this object it will never be released causing a memory leak. 因为现在您指向一个新的内存位置,并且先前的内存位置具有一个由alloc init提供的保留计数为1的对象,并且由于将不再有对该对象的任何引用,因此它将永远不会释放而导致内存泄漏。

Although if you use this line: 尽管如果使用此行:

self.finalBible = [parser getBible];

Because that uses the setter, a setter releases the previous value and retains the new one, so there would not be a memory leak, but it would still be pointless to allocate that object. 因为此操作使用了setter,所以setter会释放先前的值并保留新的值,因此不会发生内存泄漏,但是分配该对象仍然毫无意义。

Since getBible does not have the new, alloc or init keyword it should return an autoreleased object, which is why the object is released in the next run loop (not guaranteed but most likely), which is why you cannot access it outside of the viewDidload() method. 由于getBible没有new, alloc or init关键字,因此它应该返回一个autoreleased对象,这就是为什么该对象在下一个运行循环中释放的原因(不保证,但是很可能),这就是为什么您不能在viewDidload()之外访问它viewDidload()方法。

You can resolve this problem by making "finalBible" variable a property of the class using 您可以通过使用以下方法使“ finalBible”变量成为类的属性来解决此问题:

@property(nonatomic, retain) Bible finalBible; @property(非原子性,保留)圣经finalBible; //this is in the .h file @synthesis finalBible; //这在.h文件中@synthesis finalBible; // at the top of .m file //在.m文件的顶部

All the reference to "finalBible" should be made as "self.finalBible" 所有对“ finalBible”的引用都应作为“ self.finalBible”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM