iOS - App崩溃了Garbagecollector的错误?

时间:2012-05-01 19:31:16

标签: ios crash garbage-collection alloc

我和我的团队正在开发一个测验应用程序,我们有一个视图,我们只需在标签和按钮上重新加载文本。 现在,当我们开始测验时,有2个循环从数据库加载问题和回答。在这些循环中,我们初始化在.h文件中声明的对象。 所以我们做的是:obj = [[class alloc] initwith:stuff]; 它完美地工作,直到第6次我们调用2循环的方法。有时它会在第一个循环中崩溃,有时会在第二个循环中崩溃。 现在奇怪的是,如果我们在“再次播放”按钮上调用该方法两次它将在第3次崩溃(方法称为6次然后=崩溃),所以我们认为它与内存有关或所以。 我们尝试清理项目,在iPad和模拟器上运行它。没有效果。 错误消息是我们在第一个循环中填充的数组在第二个循环中是空的。

我暂时无法给你一个代码管,但最简单的方法是在用户按下“再次播放”按钮时重置应用程序。有没有简单的方法来做到这一点? 如果应用程序只是关闭并重新打开闪屏,那也没关系。

如果您现在无法提出任何建议,我明天会添加一个代码

提前致谢

编辑: SIGABRT 这是错误消息:SoccerQuiz [1563:f803] *由于未捕获的异常'NSRangeException'终止应用程序,原因:'* - [__ NSArrayM objectAtIndex:]:索引0超出空数组的边界' * 第一次抛出调用堆栈: (0x159e022 0x172fcd6 0x158ad88 0x4719 0x3455 0x159fe99 0xe214e 0xe20e6 0x188ade 0x188fa7 0x188266 0x1073c0 0x1075e6 0xeddc4 0xe1634 0x1488ef5 0x1572195 0x14d6ff2 0x14d58da 0x14d4d84 0x14d4c9b 0x14877d8 0x148788a 0xdf626 0x20ed 0x2055) 终止调用抛出异常(lldb)

我的代码:

-(NSMutableArray*) readFromDatabase{

//if modus is true 20 questions will be loaded(untested). we set mds to 10 for now which works for the first 5 times and then crashes the 6th time
int mds = 0;
if (modus)
 mds = 20;
 else mds = 10;
bool loop = true;

//a_data is the array in which the data object is. it is filled with the questions and answeres    
NSMutableArray * a_data = [[NSMutableArray alloc] init];
//check_id is the array in which the question ids from the database are saved
NSMutableArray * check_id = [[NSMutableArray alloc] init];


//ant is the array in which the 4 possible answers are saved.
NSMutableArray *ant = [[NSMutableArray alloc] init];

//in id_frage the id of the question is saved and in frage the question itself
NSString *id_frage = [[NSString alloc] init];
NSString *frage = [[NSString alloc] init];

//in sql_id the statement for the question is saved
NSString *sql_id = [[NSString alloc] initWithFormat:@"select id from QQUESTION where level = %@ order by random() limit 1", difficulty];

//in the method sqlquery we get data from the database
id_frage = [[self sqlquery: sql_id with:@"Q"] objectAtIndex:0];

[check_id addObject:id_frage];


NSLog(@"1");
//we use these loops to read unique question ids from the database, as you can see random questions are loaded from the database (sql_id statement)
for (int z = 0; z < mds; z++)
{
    while (loop)
    {
    for (int y = 0; y <= check_id.count; y++)
    {
        //this loop checks if the question id is already in check_id
        if ([[check_id objectAtIndex:y] isEqualToString:id_frage])
        {
            id_frage = [[self sqlquery: sql_id with:@"Q"] objectAtIndex:0];    

            break;

        }
        else { 
            //if the id doesnt already exit, it will be added to the check_id array
            if (y == check_id.count-1)
            {
            [check_id addObject:id_frage];
            loop = false;
            break; 
            }
        }
    }
    }
    loop = true;
    id_frage = [[self sqlquery: sql_id with:@"Q"] objectAtIndex:0];
}

      NSLog(@"2");




//this loops loads the questions and answers that fit to the question ids
for (int x = 0; x < mds; x++)
{


//sql_q statement for the questions
NSString *sql_q = [[NSString alloc] initWithFormat:@"select TEXT from QQUESTIONTEXT where ID_QUESTION = '%@' and LANGUAGE = '%@'", [check_id objectAtIndex:x], language];

frage = [[self sqlquery:sql_q with:@"Q" ]objectAtIndex:0];

//sql_a statement for the answers    
NSString *sql_a = [[NSString alloc] initWithFormat:@"select answer.correct, answertext.text from QANSWER as answer, QANSWERTEXT as answertext where answer.ID_QUESTION='%@' and answer.ID = answertext.ID_ANSWER and answertext.LANGUAGE = '%@'", [check_id objectAtIndex:x], language];

ant = [self sqlquery: sql_a with:@"A"];    

    //this loop sets the right answer at the first position of the array
    for(int a = 0; a<ant.count-1; a++)
    {
        if([[ant objectAtIndex:a] isEqualToString:@"1"])
        {
            a++;
            NSString *h = [[NSString alloc]initWithFormat:[ant objectAtIndex:1]];

            [ant replaceObjectAtIndex:1 withObject:[ant objectAtIndex:a]];
            [ant replaceObjectAtIndex:a withObject:h];
            a--;

            break;

        }

    }

//this data object 'd' is filled with a question and 4 answers and 10 or 20 will be added to a_data which will be returned
d = [[data alloc] initFrage:frage mitAntwort1:[ant objectAtIndex:1] Antwort2:[ant objectAtIndex:3] Antwort3:[ant objectAtIndex:5] Antwort4:[ant objectAtIndex:7]];
[a_data addObject:d];
}

 NSLog(@"3");




return a_data;

}

2 个答案:

答案 0 :(得分:3)

iOS上没有垃圾收集器 - 有手动或自动引用计数(ARC)。在任何一种情况下,都使用retain和release对对象进行引用计数。使用ARC,您不必自己进行这些调用,但这并不意味着您仍然无法遇到问题。

如果没有您的代码或任何信息,我只能提供一般性建议。我假设您的崩溃是EXC_BAD_ACCESS或某些等效的。

我写了一篇博客来解释这个问题以及如何排除故障

http://loufranco.com/blog/files/Understanding-EXC_BAD_ACCESS.html

在你的情况下,这就是我要做的事情

  1. 运行分析并修复标记的每个问题
  2. 打开僵尸并重现您的问题。如果你正在与一个僵尸对象交谈,现在应该更容易看到发生了什么。
  3. 如果失败,请打开Debug Malloc并使用我博客中链接的工具来调试问题。

    基于问题编辑的编辑:

    你得到一个例外 - 在你提供的代码中,有几个objectAtIndex调用 - 使用这里的指令在异常上创建一个断点:

    http://www.dosomethinghere.com/2011/04/18/xcode-4-exception-breakpoint/

    告诉我们确切的行。

    基本上,你不能在空数组上调用objectAtIndex为0 - 所以你需要先检查长度。

答案 1 :(得分:0)

在iOS中没有垃圾收集器功能。
相反,有ARC(自动参考计数)
Apple在这里讨论ARC:https://developer.apple.com/technologies/ios5/
ARC是编译器技术,使用保留计数来跟踪对象 因此,应用程序崩溃的最可能原因是访问已发布的对象。 这通常会导致编译器警告您访问不良! 在头文件中,确保使用
正确保留对象 @property(nonatomic,retain)Object * myobject;
希望这有帮助!