IOS nsstring 的发布和分配消息差异

IOS Release and assignment messages differences for nsstring

我正在研究内存管理概念。我创建了一个 string1 并将那个 string1 分配给另一个 string2,现在我发布这个 string1。 这里 string2 保留计数为 1,但在 NSLog 语句中它给出了 EXC Bad 访问权限。

当我分配字符串时

NSString * string1 = [[NSString alloc]initWithFormat:@"hello"];
string2 = string1;

NSLog(@"string1 memory address = %p, string2 memory address = %p", &string1, &string2);

[string1 release];

NSLog(@"[string2 retainCount] = %lu", (unsigned long)[string2 retainCount]);
NSLog(@"string2 = %@", string2); // here app is crashing

这是否意味着 string2 也有一个自动释放消息,因为如果我做 string2 = [string1 copy]; 而不是 string2 = string1; 它不会崩溃。 所以我想问一下崩溃是否是因为它有 string2 的自动释放消息以及它与 string2 释放命令有什么关系。 请指教!

如果您在 Objective-C 中使用手动内存管理,则赋值不会更改对象的保留计数。你一定要使用它,否则,你不能在代码中调用 release 方法。

因此,您的代码执行以下操作。它创建 NSString 保留计数 = 1 的对象,并将其分配给 string1 指针。之后,您将 string1 分配给 string2。现在你有 2 个指向同一个对象的指针,并且这个对象的保留计数仍然是 1。然后你释放对象,它立即释放。在那之后你遇到了崩溃:

NSString * string1 = [[NSString alloc]initWithFormat:@"hello"]; // string retain count is 1 
string2 = string1; // 2 pointers to same string, retain count is still 1
[string1 release]; // string is deallocated when retain count drops to 0
NSLog(@"string2 = %@", string2); // here app is crashing

要解决这个问题,您可以在做作业时使用 retain

NSString * string1 = [[NSString alloc]initWithFormat:@"hello"]; // string retain count is 1
string2 = [string1 retain]; // 2 pointers to same string, retain count is 2
[string1 release]; // string retain count back to 1
NSLog(@"string2 = %@", string2); // no crash

此外,您可以使用 copy。请注意,对于 NSString,copy 实际上并不复制对象,它只是调用 retain。无需执行实际复制,因为 NSString 是不可变的,无法更改。如果我们使用 NSMutableString,事情就会改变:

NSMutableString * string1 = [[NSMutableString alloc]initWithFormat:@"hello"]; // string retain count is 1
NSMutableString * string2 = [string1 copy]; // 2 separate strings, both have retain count 1
[string1 release]; // string1 is deallocated
NSLog(@"string2 = %@", string2); // no crash, string2 retain count is 1

或者,您可以使用 ARC。它会在编译时插入相应的 retain/release 调用。代码将如下所示:

NSString * string1 = [[NSString alloc]initWithFormat:@"hello"];
string2 = string1;
string1 = nil;
NSLog(@"string2 = %@", string2); // no crash

我建议先了解手动内存管理,然后再迁移到 ARC。