【问题标题】:pointer memory management misunderstanding w/ objective-c带有objective-c的指针内存管理误解
【发布时间】:2010-11-14 00:55:57
【问题描述】:

我使用的是 iPhone SDK 3.0,但我认为这是对 w/c 和内存管理的工作方式的普遍误解。

我已经像这样覆盖了 viewWillAppear 方法

@implementation MyViewController
- (void)viewWillAppear:(BOOL)animated {
  NSArray *items = [NSArray arrayWithOjbects:self.searchButton, self.trashCan, nil];
  [self.bottomBar setItems:items animated:YES];
}
// other stuff...
@end

当我尝试从上面的视图控制器切换并切换回来时,一切正常。

但是,我倾向于“释放”指向“items”的原始指针,因为我认为对 NSArray 的引用现在由 bottomBar 持有。 但是当我这样做(参见下面的代码)并尝试从 UIViewController 切换时,我收到内存管理错误(-[CFArray count]: message sent to deallocated instance 0xd5f530)。

- (void)viewWillAppear:(BOOL)animated {
  NSArray *items = [NSArray arrayWithOjbects:self.searchButton, self.trashCan, nil];
  [self.bottomBar setItems:items animated:YES];
  [items release];
} 

在这种情况下我是否需要发布项目?还是我做错了什么? 显然,经验证据表明我不应该发布“项目”,但我不清楚为什么会这样。

感谢任何信息/“指针”!

【问题讨论】:

  • 谢谢大家!并感谢您的链接。

标签: objective-c memory-management nsarray


【解决方案1】:

你不需要释放它,因为你从来没有初始化过它。 [NSArray arrayWithObjects:...] 返回一个自动释放的对象。你不负责释放它,因为当它从方法返回时,它已经发送了自动释放消息。你只需要释放你初始化的东西! (如果您使用了[[NSArray alloc] initWithObjects:...],您将不得不这样做。)

【讨论】:

  • 确实你不负责释放它,但不能保证它是一个自动释放的对象。你只知道你不拥有它。在 developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/…> 阅读规则。
【解决方案2】:

当您在NSArray 上致电arrayWithObjects: 时:

NSArray *items = [NSArray arrayWithObjects:self.searchButton, self.trashCan, nil];

您将返回一个自动释放的数组。数组自动释放返回给您,因为您没有调用allocnew 或包含copy 的方法。这表示您不需要内存管理该对象。 (查看Memory Management Programming Guide for Cocoa了解更多信息)

但是,当您在 self.bottomBar 上调用 setItems 时,它会被保留,将数组作为参数传递,将其保留计数增加到 1,但随后您释放它,将其保留计数返回为零,这导致它被释放。

由于数组由self.bottomBar 保留,这意味着它正在管理数组的内存。当不再需要时,会释放数组,暗示类不再需要数组,这才是管理内存的正确方式。

【讨论】:

  • 确实你不负责释放它,但不能保证它是一个自动释放的对象。你只知道你不拥有它。在 developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/…> 阅读规则
【解决方案3】:

看在老天的份上,请把人们指向Memory Management Rules。不要转述它们。不要说“返回一个自动释放的对象”(这不一定是真的,即使它是真的也无关紧要)。只需将他们指向规则即可。

规则一共有9个段落!没有必要对它们进行释义、缩略或重述。它们清晰、简洁、明确。

阅读规则,遵守规则,你不会有内存管理问题。

【讨论】:

    【解决方案4】:

    这是简短的版本:

    +[NSArray arrayWithObjects:] 返回一个你不拥有的对象,所以不,你不应该释放它。

    另一方面,如果你这样做了:

    NSArray *items = [[NSArray alloc] initWithObjects:self.searchButton, self.trashCan, nil];
    

    这会创建一个保留计数为 1 的对象,因此您需要释放它以防止它泄漏。

    查看Memory Management Programming Guide for Cocoa了解更多详情。

    【讨论】:

    • 确实你不负责释放它,但不能保证它是一个自动释放的对象。你只知道你不拥有它。在 developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/…> 阅读规则
    • 我知道区别,谢谢。我试图以一种 Objective-C 新手能够理解的方式进行解释,这就是为什么如果他想真正深入学习这个主题,我会链接到你指向我的相同文档。
    • 我同意你的答案是以这种方式失败的最好的答案。但是,如果您知道区别,请不要给新手增加困惑。一旦你开始谈论自动释放的对象,他们就会开始考虑保留计数以及从那里开始的一切。内存管理规则简单易懂,对自动释放或保留计数只字未提,但新手经常会因为收到的建议谈到这些事情而感到困惑。
    • 我不同意这就像你想象的那么重要,但没关系。我将编辑我的答案以使其更正确。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-22
    • 1970-01-01
    • 2015-05-19
    • 1970-01-01
    • 2020-01-27
    • 1970-01-01
    相关资源
    最近更新 更多