iPhone开发:如何在Objective-C中捕获异常/错误?

9
我希望我的应用程序永远不会傻傻地崩溃。我知道代码质量是解决这个问题的根本方法。但是,当发生意外错误时,我仍然需要应用程序从不崩溃。这是我想尝试的代码。
-(void)testException
{
    @try
    {
        NSString* str;
        [str release];
    }
    @catch(NSException* ex)
    {
        NSLog(@"Bug captured");
    }
}

我知道这个不起作用。因为release从未引发异常。这是我的问题:
  1. 如何实现这种目标,捕获bug但没有崩溃?
  2. 我怎么知道哪个系统库会引发异常,以便我可以编写一些代码并知道它的运行情况?
这是我阅读过的内容:
  • a. Cocoa的异常编程主题
  • b. Cocoa错误处理编程指南
我来自有经验的Microsoft程序员背景,在那里捕获异常或意外异常总是可以防止我的程序在非常恶劣的环境下崩溃。
你们(Mac天才程序员)是如何实现无崩溃程序的?分享一下你们的经验。
3个回答

12

Objective-C是一种无管理的运行时环境;编译后的代码直接在CPU上运行,而不是在虚拟机中运行。这意味着你没有完全监督程序的层面,以捕捉像在.NET VM或JVM中运行时那样的每一个可能的故障模式。简单来说就是唯一确定程序不会崩溃的方法是要非常仔细地编码且进行彻底的测试。即使如此,你也不能完全确定,只是认为你做到了。

Xcode的最新版本集成了Clang静态分析器(在构建菜单中的“构建并分析”选项),可以识别某些潜在错误类型--我相当确定它会标记上面的例子。但是这里没有魔法弹药,唯一的解决方案是努力工作。


4

测试测试测试测试测试

你可以花一整天编写可能永远不会发生的异常处理代码,或者你可以创建全面的测试套件,并仅为实际发生的情况编写异常处理程序。

这就是为什么我几乎从不编写异常处理程序的原因。如果您修复了导致异常的根本问题,那么您就不需要处理任何内容。

当然,有时候您无法确保方法调用不会引起异常,您需要做好准备,但将所有内容包装在@try/@catch块中绝对不是解决方案。


3

你遇到的问题是str从未初始化,这意味着str可能指向nil(但这不是保证)。它肯定指向垃圾。

如果你逐步执行代码,我几乎可以保证你的释放调用了nil,在Objective-C中这是完全有效的。

尝试这样做:

NSString *str = [[NSString alloc] initWithString:@"a string"];
[str release];
[str release];

调用 release 不会释放对象,它只是将保留计数减少 1。当对象的保留计数为 0 时,

[self dealloc];

自动调用。

如果上述代码没有立即抛出异常,则可能是因为实际的释放消息被延迟到某个未来的时间点(我不确定在retain计数达到0后dealloc何时被调用,我认为它会立即并在同一个线程上被调用,但其他一些Cocoa专家肯定知道)。

您可以添加一个NSObject类别,并实现dealloc和release方法,尝试在其中捕获异常。

- (void)dealloc{

 @try
    {
        [super dealloc];
    }
 @catch(NSException* ex)
    {
        NSLog(@"Bug captured");
    }

}



- (void)release{

     @try
        {
            [super release];
        }
     @catch(NSException* ex)
        {
            NSLog(@"Bug captured");
        }

    }

额外的好处是,由于它是NSObject的一个类别,所以此代码将适用于应用程序中的每个对象。

然而,要完整的话,如果你只是遵循内存管理规则,那么就没问题了。


感谢您的回答。您的回答帮助我更好地理解了内存管理,并扩展了我对Objective C的知识。然而,我已经尝试了代码,它们从未崩溃过(如果可能的话,我释放了4次,引用计数应该是-3)。但是根本没有发生崩溃,也没有抛出任何异常。我知道它迟早会崩溃。但不知道什么时候。所以回到基础,有没有办法避免崩溃? - angrysword
不要担心保留计数。你永远不应该检查它,因为出于各种原因,它永远不是你认为它应该是的。你必须逐个方法地处理内存管理。在Stackoverflow和Google上搜索Cocoa内存管理。有很多资源可以帮助你。一开始学习可能很难,但会变得更加自动化。 - Corey Floyd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接