当前位置:  开发笔记 > IOS > 正文

目标C内存管理混乱

如何解决《目标C内存管理混乱》经验,为你挑选了1个好方法。

我正在阅读关于内存管理的苹果文档,并遇到了一些我不明白的内容.基本上,我不明白为什么不需要通过"getter"方法保留实例变量.我写了这个小程序,看看会发生什么.我以为会有崩溃,但我显然错过了一些东西.

//  main.m
//  Test
//


#import 
#import "Test.h"

int main(int argc, char *argv[])
{
    NSAutoreleasePool *p = [[NSAutoreleasePool alloc] init];

    //Initialize the test object
    Test *t = [[Test alloc] init];

    //Set the value to 5
    [t setMyNum:[NSNumber numberWithInt:5]];

    //Save a temp number that points to the original number
    NSNumber *tempNum = [t myNum];

    //release old number and retain new
    [t setMyNum:[NSNumber numberWithInt:7]];

    //Shouldn't this crash because tempNum is pointing to a deallocated NSNumber???
    NSLog(@"the number is %@",tempNum);

    [p drain];
    return 0;
}

tempNum不指向解除分配的对象吗?

所有帮助表示赞赏.

编辑

这是getter和setter方法中的代码

#import "Test.h"


@implementation Test
- (void)setMyNum:(NSNumber *)newNum {
    [newNum retain];
    [myNum release];
    myNum = newNum;
}

-(NSNumber *)myNum {
    return myNum;
}
@end

正如您所看到的,我正在调用旧对象上的release.

编辑

有人建议,我认为这是正确的,因为tempNum仍然存在的原因是因为它尚未从池中自动释放.但即使在NSLog消息之前将[pool drain]移动到右边,也没有崩溃??? 奇怪的.



1> Jason..:

由于您没有显式释放任何对象,因此在允许自动释放池耗尽之前不会释放任何内容.尝试[p drain]在最后一次NSLog通话前插入.它应该崩溃NSLog调用.

此外,如果您没有在setMyNum:方法中保留NSNumber,您会发现如果[p drain]在分配tempNum之前添加它将会崩溃.

为了澄清原始问题,调用getter方法不会(也不应该)必然意味着调用者想要获取所有权(即保留)变量.如果是这种情况,此代码将泄漏:

NSLog("Number is %@", [t myNum]);

此外,NSNumber似乎有一个优化,对于小数字,它们缓存NSNumber对象,保留额外的副本,并返回该版本.因此对于小常量,[NSNumber numberWithInt: N]将返回具有2个引用计数的对象(可通过[theNumber retainCount]).要明确地看到会发生什么,在程序中使用一个更大的常量,NSNumber将保留一个引用计数为1的"新鲜"对象(也将自动释放).


好吧,看起来NSNumber缓存了一些NSNumber对象(即它保持类级别并保留它们的额外副本)用于小整数.尝试numberWithInt:654321.那会崩溃!
推荐阅读
雯颜哥_135
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有