2012-04-03 104 views
0

我理解這個代碼的問題:釋放或自動釋放的對象

- (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

問題是,您正在將對象分配給selectedAmountOfBits 兩次

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

分配您擁有並將其分配給selectedAmountOfBits一個新的NSNumber對象。

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]; 
} 
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]; 
} 
+0

感謝您爲我解決問題:) – Cubia 2012-04-03 23:39:39

+0

UIAdam也是正確的 - 他在我做之前幾分鐘就拿到了它);) – iccir 2012-04-03 23:39:56