ios Objective-C 中的自动引用计数不能防止或最小化哪种泄漏?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6260256/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 20:14:58  来源:igfitidea点击:

What kind of leaks does automatic reference counting in Objective-C not prevent or minimize?

iosobjective-cmacosmemory-leaksautomatic-ref-counting

提问by BoltClock

In the Mac and iOS platforms, memory leaks are often caused by unreleased pointers. Traditionally, it has always been of utmost importance to check your allocs, copies and retains to make sure each has a corresponding release message.

在 Mac 和 iOS 平台中,内存泄漏往往是由未释放的指针引起的。传统上,检查您的分配、副本和保留以确保每个都有相应的发布消息一直是最重要的。

The toolchain that comes with Xcode 4.2 introduces automatic reference counting (ARC) with the latest version of the LLVM compiler, that totally does away with this problem by getting the compiler to memory-manage your stuff for you. That's pretty cool, and it does cut lots of unnecessary, mundane development time and prevent a lot of careless memory leaks that are easy to fix with proper retain/release balance. Even autorelease pools need to be managed differently when you enable ARC for your Mac and iOS apps (as you shouldn't allocate your own NSAutoreleasePools anymore).

Xcode 4.2 附带的工具链在最新版本的LLVM 编译器中引入了自动引用计数 (ARC),通过让编译器为您进行内存管理,完全解决了这个问题。这非常酷,它确实减少了许多不必要的、平凡的开发时间,并防止了许多粗心的内存泄漏,这些泄漏很容易通过适当的保留/释放平衡来修复。当您为 Mac 和 iOS 应用程序启用 ARC 时,甚至自动释放池也需要进行不同的管理(因为您不应再分配自己的NSAutoreleasePools)。

But what othermemory leaks does it notprevent that I still have to watch out for?

但是还有哪些其他内存泄漏不能阻止我仍然需要注意?

As a bonus, what are the differences between ARC on Mac OS X and iOS, and garbage collection on Mac OS X?

作为奖励,Mac OS X 和 iOS 上的 ARC 与 Mac OS X 上的垃圾收集有什么区别?

回答by Brad Larson

The primary memory-related problem you'll still need to be aware of is retain cycles. This occurs when one object has a strong pointer to another, but the target object has a strong pointer back to the original. Even when all other references to these objects are removed, they still will hold on to one another and will not be released. This can also happen indirectly, by a chain of objects that might have the last one in the chain referring back to an earlier object.

您仍然需要注意的主要内存相关问题是保留周期。当一个对象具有指向另一个对象的强指针,但目标对象具有指向原始对象的强指针时,就会发生这种情况。即使删除了对这些对象的所有其他引用,它们仍然会相互保持并且不会被释放。这也可以通过一系列对象间接发生,这些对象链中的最后一个对象可能会引用回较早的对象。

It is for this reason that the __unsafe_unretainedand __weakownership qualifiers exist. The former will not retain any object it points to, but leaves open the possibility of that object going away and it pointing to bad memory, whereas the latter doesn't retain the object and automatically sets itself to nil when its target is deallocated. Of the two, __weakis generally preferred on platforms that support it.

正是出于这个原因,存在__unsafe_unretained__weak所有权限定符。前者不会保留它指向的任何对象,但留下了该对象消失并指向坏内存的可能性,而后者不保留该对象并在其目标被释放时自动将自身设置为 nil。在__weak支持它的平台上,通常首选这两者。

You would use these qualifiers for things like delegates, where you don't want the object to retain its delegate and potentially lead to a cycle.

您可以将这些限定符用于诸如委托之类的事情,您不希望对象保留其委托并可能导致循环。

Another couple of significant memory-related concerns are the handling of Core Foundation objects and memory allocated using malloc()for types like char*. ARC does not manage these types, only Objective-C objects, so you'll still need to deal with them yourself. Core Foundation types can be particularly tricky, because sometimes they need to be bridged across to matching Objective-C objects, and vice versa. This means that control needs to be transferred back and forth from ARC when bridging between CF types and Objective-C. Some keywords related to this bridging have been added, and Mike Ash has a great description of various bridging cases in his lengthy ARC writeup.

的显著内存相关的问题的另一对夫妇是核心基础的处理对象和使用内存分配malloc()的类型,如char*。ARC 不管理这些类型,只管理 Objective-C 对象,因此您仍然需要自己处理它们。Core Foundation 类型可能特别棘手,因为有时需要将它们桥接到匹配的 Objective-C 对象,反之亦然。这意味着在 CF 类型和 Objective-C 之间进行桥接时,控制需要从 ARC 来回转移。添加了一些与此桥接相关的关键字,Mike Ash 在他冗长的 ARC 文章中对各种桥接案例进行了很好的描述。

In addition to this, there are several other less frequent, but still potentially problematic cases, which the published specificationgoes into in detail.

除此之外,还有其他一些不太常见但仍有潜在问题的情况,已发布的规范详细介绍了这些情况。

Much of the new behavior, based on keeping objects around as long as there is a strong pointer to them, is very similar to garbage collection on the Mac. However, the technical underpinnings are very different. Rather than having a garbage collector process that runs at regular intervals to clean up objects no longer being pointed to, this style of memory management relies on the rigid retain / release rules we all need to obey in Objective-C.

许多新行为基于只要有指向对象的强指针就将对象保留在周围,这与 Mac 上的垃圾收集非常相似。但是,技术基础非常不同。这种内存管理风格依赖于我们在 Objective-C 中都需要遵守的严格的保留/释放规则,而不是定期运行以清理不再指向的对象的垃圾收集器进程。

ARC simply takes the repetitive memory management tasks we've had to do for years and offloads them to the compiler so we never have to worry about them again. This way, you don't have the halting problems or sawtooth memory profiles experienced on garbage collected platforms. I've experienced both of these in my garbage collected Mac applications, and am eager to see how they behave under ARC.

ARC 只是将我们多年来不得不做的重复内存管理任务卸载给编译器,这样我们就不必再担心它们了。这样,您就不会遇到在垃圾收集平台上遇到的停机问题或锯齿状内存配置文件。我在我的垃圾收集 Mac 应用程序中经历了这两种情况,并且很想知道它们在 ARC 下的行为。

For more on garbage collection vs. ARC, see this very interesting response by Chris Lattner on the Objective-C mailing list, where he lists many advantages of ARC over Objective-C 2.0 garbage collection. I've run into several of the GC issues he describes.

有关垃圾收集与 ARC 的更多信息,请参阅Chris Lattner 在 Objective-C 邮件列表上的这个非常有趣的回复,他列出了 ARC 相对于 Objective-C 2.0 垃圾收集的许多优点。我遇到了他描述的几个 GC 问题。

回答by Stripes

ARC won't help you with non-ObjC memory, for example if you malloc()something, you still need to free()it.

ARC 不会帮助你处理非 ObjC 内存,例如,如果你有malloc()什么,你仍然需要free()它。

ARC can be fooled by performSelector:if the compiler can't figure out what the selector is (the compiler will generate a warning on that).

performSelector:如果编译器无法确定选择器是什么(编译器将生成警告),则ARC 可能会被愚弄。

ARC will also generate code following ObjC naming conventions, so if you mix ARC and MRC code you can get surprising results if the MRC code doesn't do what the compiler thinks the names promise.

ARC 还将生成遵循 ObjC 命名约定的代码,因此,如果混合使用 ARC 和 MRC 代码,如果 MRC 代码没有执行编译器认为名称所承诺的那样,您会得到令人惊讶的结果。

回答by Ed-E G

I experienced memory leaks in my application due the following 4 issues:

由于以下 4 个问题,我在我的应用程序中遇到了内存泄漏:

  1. Not invalidating NSTimers when dismissing view controllers
  2. Forgetting to remove any observers to NSNotificationCenter when dismissing the view controller.
  3. Keeping strong references to self in blocks.
  4. Using strong references to delegates in view controller properties
  1. 关闭视图控制器时不会使 NSTimers 失效
  2. 关闭视图控制器时忘记删除 NSNotificationCenter 的任何观察者。
  3. 在块中保持对 self 的强引用。
  4. 在视图控制器属性中使用对委托的强引用

Luckily I came across the following blog post and was able to correct them: http://www.reigndesign.com/blog/debugging-retain-cycles-in-objective-c-four-likely-culprits/

幸运的是,我遇到了以下博客文章并能够更正它们:http: //www.reigndesign.com/blog/debugging-retain-cycles-in-objective-c-four-likely-culprits/

回答by WILL K.

Xcode 9 provides a great tool for finding that kind of issues. It is called: "Debug Memory Graph". Using it you can find your leaked object by class type and you can see clearly who holds a strong reference to it, by releasing it from there solves your problem. It is also detects memory cycles.

Xcode 9 提供了一个很好的工具来查找这类问题。它被称为:“调试内存图”。使用它,您可以按类类型找到泄漏的对象,并且您可以清楚地看到谁拥有对它的强引用,通过从那里释放它可以解决您的问题。它还检测内存周期。

See more info about how to use it

查看有关如何使用它的更多信息

回答by MaddTheSane

ARC will also not manage CoreFoundation types. You can 'bridge' them (Using CFBridgingRelease()) but only if you are going to use it as an Objective-C/Cocoa object. Note that CFBridgingRelease just decrements the CoreFoundation retain count by 1 and moves it to Objective-C's ARC.

ARC 也不会管理 CoreFoundation 类型。您可以“桥接”它们(使用CFBridgingRelease()),但前提是您要将其用作 Objective-C/Cocoa 对象。请注意,CFBridgingRelease 只是将 CoreFoundation 保留计数减 1,并将其移动到 Objective-C 的 ARC。