【问题标题】:IOS Release and assignment messages differences for nsstringnsstring 的 IOS 版本和分配消息差异
【发布时间】:2017-01-30 01:29:25
【问题描述】:

我正在学习内存管理概念。我创建了一个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释放命令的关系。 请指教!

【问题讨论】:

标签: ios objective-c memory-management nsstring manual-retain-release


【解决方案1】:

如果您在 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。它将在编译时插入相应的保留/释放调用。然后代码将如下所示:

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

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

【讨论】:

  • 感谢详细解释,只是一个疑问,string2 = string1; // 2 个指向同一个字符串的指针,retain count 仍然是 1 是否意味着字符串 1 和字符串 2 的内存地址相同,因为当我打印内存地址时它们是不同的。所以 2 个指向相同字符串的指针,请根据内存位置和地址进行解释。请。
  • string1string2 已经是 C 指针,您不需要在 NSLog 中获取它们的地址。改用下面的代码NSLog(@"string1 memory address = %p, string2 memory address = %p", string1, string2);,你会看到它们指向同一个地址。
  • 感谢鲍里斯的澄清。很有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-07
  • 2011-12-31
  • 2015-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多