【问题标题】:Why does "try catch" in Objective-C cause memory leak?为什么 Objective-C 中的“try catch”会导致内存泄漏?
【发布时间】:2015-01-24 07:02:32
【问题描述】:

我正在考虑 Objective-C 中 Try-Catch 的优缺点。 根据这篇文章Dispelling NSException Myths in iOS: Can We Use @try…@catch, @finally?,try-catch 并没有那么糟糕,除了它在 ARC 中会泄漏内存。

那么try-catch是如何导致内存泄漏的呢?

【问题讨论】:

  • 因为默认情况下ObjC不是异常安全的(有一个标志让它异常安全但不记得细节)
  • 这篇文章,如果这样说,那就错了。每次 Apple 有人谈到这一点时,他们都会非常明确地说:“不要将异常作为一种进行流控制的方式;异常是针对异常的、不需要的情况,意味着你想崩溃。”如果您认为需要抛出自己的异常,请再想一想。 (话虽如此,我希望 AVFoundation 开发办公室的人能收到这份备忘录。)
  • 知道它确实救了我的命!

标签: ios objective-c memory-leaks error-handling try-catch


【解决方案1】:

首先:异常在 Objective-C 中有不同的语义。异常意味着由于编程错误而发生了完全错误,并且应用程序的进一步执行没有用。终止它!要处理“预期错误”(例如用户输入不足或服务器没有响应等),请使用Cocoa's error handling pattern。 (这样做的原因是异常在许多情况下似乎很方便,但在其他情况下很难处理,即在对象构造时。阅读 C++ 中的异常。这很痛苦。)

对于您的问题:ARC 添加了额外的代码来处理内存管理。必须执行此代码来处理内存管理,尤其是。释放对象。如果在此之前发生异常,则控制流永远不会到达 release 语句。内存泄漏。

- (void)method
{
   id reference = …;
   // Some ARC code to retain the object, reference points to.
   … 
   @throw …
   …
   // reference loses its extent, because of method termination
   // Some ARC code to release the object, reference points to.
}

如果出现异常,则立即离开该方法,并且永远不会执行 ARC 代码和释放对象的方法的结尾。这就是泄漏。

您可以通过使用-fobjc-arc-exceptions 选项编译源来更改此行为。

http://clang.llvm.org/docs/AutomaticReferenceCounting.html#exceptions

这将添加代码以使 ARC 异常安全,从而导致运行时损失。但正如本答案开头所述,在 Cocoa 开发中几乎没有理由这样做。

【讨论】:

  • 异常在 Obj-C 中的语义与在 C++ 中的语义不同。事实上,它们的实现方式相同,行为由平台 ABI 定义。您的意思是,Cocoa 中的异常具有不同的语义,或者更确切地说,[几乎所有]Cocoa 中的约定 是仅为致命错误保留异常。
  • 显然“实现”和“语义”是两个不同的东西。因此,“异常在 Obj-C 中的语义与在 C++ 中没有不同。事实上,它们的实现方式相同”这样的说法毫无意义。我描述了A中的差异。没有理由在评论中重复解释。
  • 我不同意在目标 c 中异常应该总是致命的。一个示例是 NSSecureCoding,如果某些数据无法解码,它将引发异常。数据可能超出您的控制范围,应用程序当然不应该在无法处理的数据上崩溃。
  • 异常在 Objective-C 中是资源密集型的。您不应该将异常用于一般的流程控制,或者仅仅表示错误。 from developer.apple.com/library/archive/documentation/Cocoa/… 但是,是的,有时甚至 Apple 也不遵循自己的规则。你必须处理它。
猜你喜欢
  • 2022-06-10
  • 1970-01-01
  • 2017-02-20
  • 2013-07-12
  • 1970-01-01
  • 2017-02-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多