仅在设备上使用iOS5 BAD_EXCESS

时间:2012-04-17 16:09:32

标签: iphone objective-c ios ipad

我正在运行后台线程来从Web服务获取数据。

要获取创建URL所需的设置,我使用此方法:

+(Settings *)getSettings
{
    Settings *settings = [[Settings alloc] init];
    NSString *path = [NSString stringWithFormat:@"Documents/Settings"];
    NSString *settingsPath = [NSHomeDirectory() stringByAppendingPathComponent:path];
    NSFileManager *fileMgr = [NSFileManager defaultManager];
    if ([fileMgr fileExistsAtPath:settingsPath]) {
        NSDictionary *settingsDictionary = [NSDictionary dictionaryWithContentsOfFile:settingsPath];
        settings.username = [settingsDictionary objectForKey:@"username"];
        settings.module = [settingsDictionary objectForKey:@"module"];
        settings.websiteUrl = [settingsDictionary objectForKey:@"websiteUrl"];

    }else
    {
        settings.username =  @"";
        settings.module =  @"";
        settings.websiteUrl =  @"";
    }
    NSLog(@"Settings = u:%@ m:%@ w:%@",settings.username,settings.module,settings.websiteUrl);
    return settings;
}

这在调试器中工作正常,但是当我在设备上运行它时,我在NSLog或任何尝试使用带有警告的数据的类上获得BAD_EXCESS:

警告:尝试使用不在框架中的块创建USE_BLOCK_IN_FRAME变量。

如果我单步执行代码,这就是设备上的代码正常工作。

有什么想法吗?

编辑: Backtrace -

#0  0x37a97eda in objc_retain ()
#1  0x37aa4be4 in objc_retainAutoreleasedReturnValue ()
#2  0x0000f84a in +[SettingData getSettings] (self=0x175e4, _cmd=0x11af9) at /Users/Jono/Dropbox/Uni/iOS5/Feedback At Tees/Feedback At Tees/SettingData.m:49
#3  0x0000fa86 in -[DataManager init] (self=0x3509e0, _cmd=0x30fd9f96) at /Users/Jono/Dropbox/Uni/iOS5/Feedback At Tees/Feedback At Tees/DataManager.m:19
#4  0x00003b46 in __35-[MasterViewController viewDidLoad]_block_invoke_0 (.block_descriptor=0x185f40) at /Users/Jono/Dropbox/Uni/iOS5/Feedback At Tees/Feedback At Tees/MasterViewController.m:70
#5  0x30b08d54 in _dispatch_call_block_and_release ()
#6  0x30b0b896 in _dispatch_worker_thread2 ()
#7  0x37a0e1ce in _pthread_wqthread ()
#8  0x37a0e0a4 in start_wqthread ()

我尝试将以下内容添加到设置的init方法中,如果我单步执行它是好的,如果我不在第二个NSLog上崩溃并出现错误:消息发送到解除分配的实例0x160d60

-(id)init
{
    if ((self=[super init]))
    {
        NSString *path = [NSString stringWithFormat:@"Documents/Settings"];
        NSString *settingsPath = [NSHomeDirectory() stringByAppendingPathComponent:path];
        NSFileManager *fileMgr = [NSFileManager defaultManager];
        if ([fileMgr fileExistsAtPath:settingsPath]) 
        {
            NSDictionary *settingsDictionary = [NSDictionary dictionaryWithContentsOfFile:settingsPath];
            self.username = [settingsDictionary objectForKey:@"username"];
            self.module = [settingsDictionary objectForKey:@"module"];
            self.websiteUrl = [settingsDictionary objectForKey:@"websiteUrl"];
            NSLog(@"Settings = u:%@ m:%@ w:%@",self.username,self.module,self.websiteUrl);
        }
        else
        {
            self.username =  @"";
            self.module =  @"";
            self.websiteUrl =  @"";
        }
    }
    NSLog(@"Settings = u:%@ m:%@ w:%@",self.username,self.module,self.websiteUrl);
    return self;
}

截图: http://postimage.org/image/4vw6uq7pp/

2 个答案:

答案 0 :(得分:2)

首先,该方法应该是retrieveSettingsdownloadSettings或者只是settings,而不是getSettings作为get,因为前缀非常特殊关于方法论证的意义(通过引用传递)。

其次,代码没有明显错误(除了settings的泄漏,但这不会导致这种崩溃)。 (我看到ARC已启用)。

最后,如果你发生了崩溃,那么发布回溯。您看到的错误消息(“USE_BLOCK_IN_FRAME”)表示您发布的代码与崩溃无关。


奇怪的崩溃,那。 OK - 警告来自调试器,与实际错误没有任何关系。

范围边界通常是编译器将发出release和/或排出自动释放池的位置。

这导致了下一个问题;怎么样?

  

如果我单步执行代码,这就是设备上的代码正常工作。

好的 - 所以,当你全速运行并且在逐步运行时工作时它不起作用。闻起来像是并发崩溃。你能发布实际崩溃的截图吗?即你确定特定的回溯是崩溃的回溯而不是崩溃发生时调试器的位置吗?

(是的,略微抓住稻草 - 这种崩溃对所显示的证据没有意义。我喜欢谜题。)


好的 - 现在我们到了某个地方。有点。在成功记录内部 if的范围后,它会崩溃之外的范围。

如何定义usernamemodulewebsiteURL?它们是strong还是最合适的copy @property声明?

答案 1 :(得分:0)

当我看到EXC_BAD_ACCESS时,我认为是时候使用 NSZombieEnabled (或者如果你可以在模拟器上重新制作它,可以使用乐器中的Zombies功能。

This thread有关于如何完成任务的说明。