我正在学习Objective-c内存管理(没有ARC),我遇到了一些常见的问题。这里曾提到过几次,所以我不是在问你“究竟是什么!?”而是“我能理解正确吗?”
问题:
文档说:
- (NSString *)fullName {
NSString *string = [[[NSString alloc] initWithFormat:@"%@ %@",
self.firstName, self.lastName] autorelease];
return string;
}
您拥有alloc返回的字符串。要遵守记忆 管理规则,你必须放弃字符串的所有权 你失去了对它的引用。 但是,如果您使用release,则为字符串 将在返回之前解除分配(并且该方法将返回 无效的对象)。使用自动释放,表示您想要 放弃所有权,但允许方法的调用者使用 在取消分配之前返回的字符串。
让我们试试:
// Method defined in one on my class:
-(NSString*) returnString {
NSString* str = [[NSString alloc] initWithString:@"returned String"];
NSLog(@"1) Address in method = %p", [str self]);
[str release];
NSLog(@"2) Address in method = %p", [str self]);
return str;
}
// In main:
NSString* str = [myObject returnString];
NSLog(@"String is: [%@]", str);
NSLog(@"3) Address in main = %p", [str self]);
-
Output:
1) Address in method = 0x100002a50
2) Address in method = 0x100002a50
String is: [returned String] // <--
3) Address in main = 0x100002a50
所以,如果我理解得很好,问题是,很难预测何时会释放出准确的内存?或者实际上,内存中的特定位置仅被标记为“已释放”,这就是全部......我是对的吗?
答案 0 :(得分:7)
NSString
非常聪明地避免分配/解除分配。这使得它成为测试释放和学习Objective C中内存管理语义的一个非常糟糕的选择。
在这种情况下,您将从文字中分配一个对象(永远不会被取消分配)。因为新初始化的对象是不可变对象的副本,所以初始化器只返回文字(再次,永远不会被解除分配)。
例如,您应该使用NSObject
或自定义派生类来测试释放。
另一个很棒的帮助是启用僵尸,因为这可以确保您立即注意到对已释放对象的第一次访问。
所以,如果我理解得很好,问题是,很难预测 什么时候准确释放内存?
好吧,对象生命周期是完全确定的(当不使用已弃用的Mac OS X垃圾收集器时)。唯一的问题是使用自动释放池:您通常不知道对象是否是自动释放的,因此如果它比您预期的更长,则无法做出任何猜测。
答案 1 :(得分:0)
NSString *str1 =@"parag";
NSString*str2=[[NSString alloc] initWithString:@"parag"];
NSLog(@"%p %p", str1, str2); //str1 and str2 both are same
// 0x100002098 0x100002098
这与内部优化有关。你必须释放str2。
注意:这依赖于编译器和initWithString:方法的未记录且无法保证的行为。两者都可能随时改变。