对象潜在泄漏警告 - 需要澄清

发布于 2024-12-08 00:24:47 字数 186 浏览 0 评论 0 原文

在我分析我的代码后,Xcode 指出了潜在的泄漏,如下所示。 带有分析结果的代码屏幕截图

这是我应该关心的事情吗?

在此代码中,设置 doublyLinkedList 的类是唯一的所有者,并在整个程序执行过程中继续管理该对象。

After I Analyzed my code, Xcode indicated a potential leak as shown below.
Screenshot of code with analysis results

Is this something I should be concerned about?

In this code, the class that sets doublyLinkedList is the sole owner and continues to manage this object throughout program execution.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦在深巷 2024-12-15 00:24:47

您收到警告的原因是因为 new 调用返回一个保留对象,然后您的 setter 可能会对其执行另一个 retain (取决于它是合成的还是手动生成)。

另外,我建议您使用标准的 alloc/init 而不是 new,这样两阶段创建就很明显了。

这更好:

if (self) {
    DoublyLinkedList *dll = [[[DoublyLinkedList alloc] init] autorelease];
    self.doublyLinkedList = dll;
}

或者只是

if (self) {
    self.doublyLinkedList = [[[DoublyLinkedList alloc] init] autorelease];
}

The reason you're getting the warning is because the new call returns a retained object, and then your setter is probably doing another retain on it (depends on whether it's synthesized or manually generated).

Also, I would recommend you use the standard alloc/init instead of new, so that the two-phase creation is obvious.

This is better:

if (self) {
    DoublyLinkedList *dll = [[[DoublyLinkedList alloc] init] autorelease];
    self.doublyLinkedList = dll;
}

or just

if (self) {
    self.doublyLinkedList = [[[DoublyLinkedList alloc] init] autorelease];
}
北城半夏 2024-12-15 00:24:47

您可能希望这样做:

if (self) {
    DoublyLinkedList *dll = [DoublyLinkedList new];
    self.doublyLinkedList = dll;
    [dll release];
}

在标头中,将 doublyLinkedList 声明为保留的 @property

You may wish to do this instead:

if (self) {
    DoublyLinkedList *dll = [DoublyLinkedList new];
    self.doublyLinkedList = dll;
    [dll release];
}

In the header, declare doublyLinkedList a @property that is retained.

溺渁∝ 2024-12-15 00:24:47

您有“潜在泄漏”,因为分析器发现您已经为 DoublyLinkedList 实例分配了内存(使用 new),将其放入名为 dll 的局部变量中,并且没有在同一范围内释放该内存。

假设您设置的 doublyLinkedList 成员碰巧也是声明为 retaining 的属性,那么您也会遇到实际泄漏,因为您过度保留了在此处创建的 DoublyLinkedList

所有权规则表示您对此实例拥有一项声明,因为您调用了 new 来创建它。当您将实例传递给 setDoublyLinkedList: 时,它会被保留,然后您就有两个声明。当 init 方法结束时,您只有一个通过 ivar/property 对该实例的引用——您已经丢失了局部变量——这意味着您拥有的所有权声明多于您拥有的引用。这是一个很好的迹象,表明您将发生泄漏。

要修复泄漏,您需要在 init 方法结束之前放弃您的声明之一。您可以通过以下两种方式之一执行此操作:设置属性后立即使用 release

DoublyLinkedList * dll = [DoublyLinkedList new];
[self setDoublyLinkedList:dll];
[dll release];

autorelease

[self setDoublyLinkedList:[[DoublyLinkedList new] autorelease]];
// Or equivalent procedures involving a temp variable

但是,应该注意的是,在 中使用 setter init 可能有问题(另请参阅Mike Ash 的文章主题),因为访问器可能(可能)产生副作用,这取决于您的对象是否已完全设置。关于这个问题似乎有两个阵营,最好阅读它并得出自己的结论,但您可能会发现它简化了分配给 ivars 而不是使用属性的初始化方法:

if( self ){
    doublyLinkedList = [DoublyLinkedList new];
}

这在术语上是完全正确的的内存管理。

最后,如果 DoublyLinkedList 是一个您拥有其代码的类,您还可以考虑编写一个方便的构造函数,它将为您返回一个新的自动释放实例。 Cocoa 中的约定是简单地在类之后命名方法,使用标准方法名称大小写,如下所示:

+ (id) doublyLinkedList {
    return [[[self alloc] init] autorelease];
}

请注意,这是一个类方法:

if( self ){
    [self setDoublyLinkedList:[DoublyLinkedList doublyLinkedList]];
}

并参见 我对“自分配对象”的回答以解释这些构造函数。

You have a "potential leak" because the Analyzer sees that you have allocated memory for a DoublyLinkedList instance (using new), put it into a local variable called dll, and not released that memory in the same scope.

Assuming that the doublyLinkedList member that you're setting happens to also be a property declared as retaining, you also have an actual leak, because you have over-retained the DoublyLinkedList that you create here.

The ownership rules say that you have one claim on this instance because you called new to create it. When you pass the instance to setDoublyLinkedList:, it is retained, and you then have two claims. When the init method ends, you only have one reference to the instance, through the ivar/property -- you've lost the local variable -- which means that you have more ownership claims than you have references. This is a good indication that you will have a leak.

To fix the leak, you need to relinquish one of your claims before the end of the init method. You can do this in one of two ways, using release as soon as the property is set:

DoublyLinkedList * dll = [DoublyLinkedList new];
[self setDoublyLinkedList:dll];
[dll release];

or autorelease:

[self setDoublyLinkedList:[[DoublyLinkedList new] autorelease]];
// Or equivalent procedures involving a temp variable

However, it should be noted that using setters in init may be problematic (see also Mike Ash's writeup on the topic), because accessors can -- potentially -- have side effects that depend on your object already being fully set up. There seem to be two camps on this issue, and it's probably best to read about it and come to your own conclusions, but you may find that it simplifies your initializer methods to assign to ivars rather than using properties:

if( self ){
    doublyLinkedList = [DoublyLinkedList new];
}

This is completely correct in terms of memory management.

Finally, if DoublyLinkedList is a class whose code you have, you can also consider writing a convenience constructor, which will return a new, autoreleased instance for you. The convention in Cocoa is to simply name the method after the class, with standard method name casing, like so:

+ (id) doublyLinkedList {
    return [[[self alloc] init] autorelease];
}

Note that this is a class method:

if( self ){
    [self setDoublyLinkedList:[DoublyLinkedList doublyLinkedList]];
}

and see my answer to "Self-allocating objects" for an explanation of these constructors.

拥抱我好吗 2024-12-15 00:24:47

如果您有一个名为“doublyLinkedList”的属性(基于给定代码的假设),并且它是“保留的”,您可以执行以下操作:

if (self) {
    DoublyLinkedList *dll = [[DoublyLinkedList alloc] init]
    self.doublyLinkedList = dll;
    [dll release];
}

If you have a property called "doublyLinkedList" (assumption based on code given), and it is "retained," you can do the following:

if (self) {
    DoublyLinkedList *dll = [[DoublyLinkedList alloc] init]
    self.doublyLinkedList = dll;
    [dll release];
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文