释放或自动释放的对象
问题描述:
我理解这个代码的问题:释放或自动释放的对象
- (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
错误。 我使用alloc
和init
初始化了对象。 为什么我不需要释放它?
答
问题是,您正在将对象分配给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];
}
答
有原始代码中的一些问题,我加//下面笔者点评:
- (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];
}
感谢您为我解决问题:) – Cubia 2012-04-03 23:39:39
UIAdam也是正确的 - 他在我做之前几分钟就拿到了它);) – iccir 2012-04-03 23:39:56