释放或自动释放对象

时间:2012-04-03 23:29:46

标签: objective-c memory-management

我在理解这段代码时遇到了问题:

- (void)subnetMaskByNumberOfSubnetBits:(id)sender{

    // ------- Sets the subnet mask when the user selects the number of bits

    NSNumberFormatter *stringToNumber = [[NSNumberFormatter alloc] init];//TURN A STRING INTO A NUMBER
    NSNumber *selectedAmountOfBits = [[NSNumber alloc] init];//CONTAINS THE SELECTED NUMBER OF BITS

        selectedAmountOfBits = [stringToNumber numberFromString:[sender objectValueOfSelectedItem]];

        [self changeSubnetMaskUsingNumberOfMaskBits:selectedAmountOfBits];

        //RELEASE
        [stringToNumber release];
        [selectedAmountOfBits release];
}

由于我发布了selectedAmountOfBits,我一直收到错误。 我使用allocinit初始化了对象。 为什么我不需要发布它?

2 个答案:

答案 0 :(得分:2)

问题是您要将对象分配给selectedAmountOfBits 两次

NSNumber *selectedAmountOfBits = [[NSNumber alloc] init];

分配您拥有的新NSNumber对象并将其分配给selectedAmountOfBits

selectedAmountOfBits = [stringToNumber numberFromString:[sender objectValueOfSelectedItem]];

自动释放的对象分配给selectedAmountOfBits。这意味着当您执行[selectedAmountOfBits release]时,您实际上是在尝试释放您不拥有的对象。您也泄漏了您创建的原始NSNumber,因为您丢失了对它的任何引用。

解决方案是删除alloc / init行,保留自动释放的NSNumber,并删除释放它的行。最终代码应如下所示:

- (void)subnetMaskByNumberOfSubnetBits:(id)sender{

    // ------- Sets the subnet mask when the user selects the number of bits

    NSNumberFormatter *stringToNumber = [[NSNumberFormatter alloc] init];//TURN A STRING INTO A NUMBER
        NSNumber *selectedAmountOfBits = [stringToNumber numberFromString:[sender objectValueOfSelectedItem]];

        [self changeSubnetMaskUsingNumberOfMaskBits:selectedAmountOfBits];

        //RELEASE
        [stringToNumber release];
}

答案 1 :(得分:0)

原始代码中存在一些问题,我添加了//!我在下面发表评论:

- (void)subnetMaskByNumberOfSubnetBits:(id)sender{
    NSNumberFormatter *stringToNumber = [[NSNumberFormatter alloc] init];

    //!i: The [[NSNumber alloc] init] is unnecessary.  You are creating a pointer to a dummy number
    //    that is immediately overwritten in the next line
    NSNumber *selectedAmountOfBits = [[NSNumber alloc] init];

    //!i: At this point, you overwrite the pointer stored in selectedAmountOfBits to point to a new
    //    NSNumber, returned by numberFromString:, and in the autorelease pool
        selectedAmountOfBits = [stringToNumber numberFromString:[sender objectValueOfSelectedItem]];

    //!i: you are now leaking the number allocated via [[NSNumber alloc] init], as you no longer have
    //    a variable tracking the pointer to it

    [self changeSubnetMaskUsingNumberOfMaskBits:selectedAmountOfBits];

    [stringToNumber release];

    //!i: You are calling -release on the number that is in the autorelease pool, not on the
    //    original number you allocated via [[NSNumber alloc] init]
    [selectedAmountOfBits release];
}

您可以按照以下方式解决此问题:

- (void)subnetMaskByNumberOfSubnetBits:(id)sender{
    NSNumberFormatter *stringToNumber = [[NSNumberFormatter alloc] init];
    NSNumber *selectedAmountOfBits = [stringToNumber numberFromString:[sender objectValueOfSelectedItem]];

    [self changeSubnetMaskUsingNumberOfMaskBits:selectedAmountOfBits];

    //!i: You still need the -release here, as stringToNumber points to the
    //    NSNumberFormatter that you created using alloc/init
    [stringToNumber release];
}