0

我正在学习内存管理概念。我创建了一个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;它不会崩溃。所以我想问一下崩溃是否是因为它有 autorelease 消息string2以及它与string2release 命令的关系。请指教!

4

1 回答 1

1

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

因此,您的代码执行以下操作。它创建NSString保留计数 = 1 的对象,并将其分配给string1指针。之后,您分配string1string2. 现在你有 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. 请注意, for NSStringcopy 实际上并不复制对象,它只是调用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。它将在编译时插入相应的保留/释放调用。然后代码将如下所示:

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

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

于 2016-09-21T18:31:19.043 回答