-1

我试图更深入地了解保留释放。这是我的代码,然后我将发布代码运行的输出。我不确定为什么当为'self'调用dealloc时保留计数永远不会为零。

其次,当我为其分配内存时,为什么 self.testNumber 的保留计数为 2,我应该使用“弱”属性来代替测试编号吗?

代码:

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    _testNumber = [[NSNumber alloc] initWithInt:10];
    testNumber = [[NSNumber alloc] initWithInt:102];
    _testInt = 105;
    self.testNumber = [[NSNumber alloc] initWithInt:101];
    NSLog(@"self.testNumber retain count = %d",[self.testNumber retainCount]);
    NSLog(@"self.label retain count = %d",[self.label retainCount]);

    self.label.text = [NSString stringWithFormat:@"%d %d %d",_testNumber.integerValue,self.testNumber.integerValue,testNumber.integerValue ];
    NSLog(@"self before release retain count = %d",[self retainCount]);

    [self release];
    NSLog(@"self after release retain count = %d",[self retainCount]);
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)dealloc {
    NSLog(@"_label after before retain count = %d",[_label retainCount]);

    [_label release];
    NSLog(@"_label after release retain count = %d",[_label retainCount]);


    [super dealloc];
}

输出:

2013-04-08 15:31:28.503 propertiesTest[5561:907] self.testNumber retain count = 2
2013-04-08 15:31:28.507 propertiesTest[5561:907] self.label retain count = 3
2013-04-08 15:31:28.509 propertiesTest[5561:907] self before release retain count = 3
2013-04-08 15:31:28.510 propertiesTest[5561:907] self after release retain count = 2
2013-04-08 15:31:28.532 propertiesTest[5561:907] _label after before retain count = 3
2013-04-08 15:31:28.534 propertiesTest[5561:907] _label after release retain count = 2
4

3 回答 3

2

系统的任何其他部分都可能保留了您的号码和标签。某些东西可能已经保留并发送了它autorelease,并且自动释放池可能尚未耗尽。您通常不应该对对象的保留计数做出假设,除非它至少与您的代码负责的保留数量一样大。

特别是,一个视图保留了它的所有子视图。这至少占标签保留计数的 +1。

您的数字的保留计数为 2,因为alloc返回一个保留计数为 1 的对象,并且您(我假设)将其存储在strongorretain属性中,这会增加其保留计数。您正在泄漏此对象,因为您负责释放它(以平衡由 执行的保留alloc)并且您没有这样做。你应该像这样重写它:

self.testNumber = [[[NSNumber alloc] initWithInt:101] autorelease];

或像这样:

self.testNumber = [[NSNumber alloc] initWithInt:101];
[self.testNumber release];

或像这样:

self.testNumber = [NSNumber numberWithInt:101];

或者,最重要的是,打开 ARC 并让编译器负责释放它。

请注意,您无需查看保留计数即可诊断此问题! 只需运行静态分析器(从 Xcode 的产品菜单中选择分析)就会显示泄漏。或者,您可以通过学习和理解 Cocoa 内存管理约定(这就是我所做的)来诊断它。阅读高级内存管理编程指南。真的没有那么先进。

如果您想了解您的号码或标签在哪里保留和发布,最好的方法是使用分配工具。有关详细信息,请参阅此答案。还有这个答案

于 2013-04-08T19:50:17.253 回答
1

从 obj-c 编码的角度来看,我不会挂断保留计数。我会考虑使用 ARC(强烈推荐恕我直言,它将帮助您编写可维护、清晰的代码并消除常见的内存管理错误)。

根据您的具体问题,_label由多个对象保留。

  1. 您的控制器将其保留在_labelivar 中。
  2. 它的superview正在保留它
  3. 根据您的代码,它可以保留在其他地方

编辑 - 如果您对 ARC 持怀疑态度,请阅读此内容

不可否认,我是一个 ARC 转换者。我确实了解手动引用计数(旧方法)。一旦我切换到 ARC,我就没有回头。我不打算在这里写长篇大论,但如果你是怀疑论者,这个链接值得一看。最后,如果您还没有准备好或者有自己的理由想要使用 MRC,那就去做吧。这是我的看法,希望有用。

http://www.learn-cocos2d.com/2012/06/mythbusting-8-reasons-arc/

于 2013-04-08T19:53:23.343 回答
0

递减retainCount然后立即转身并释放对象有什么意义?

请记住,retainCount 永远不能返回零

顺便说一句:http: //www.whentouseretaincount.com/

于 2013-04-08T19:59:48.433 回答