Objective-C - 为啥添加两个字符串会导致崩溃?

Posted

技术标签:

【中文标题】Objective-C - 为啥添加两个字符串会导致崩溃?【英文标题】:Objective-C - why adding two string is causing the crash?Objective-C - 为什么添加两个字符串会导致崩溃? 【发布时间】:2017-03-08 23:27:50 【问题描述】:

将新字符串附加到旧字符串会导致崩溃。 (如果我这样做Structios.server = @""; StructIOS.server = [StructIOS.server stringByAppendingString:@".***.com"];,则异常有效)。

struct.h:

struct iOS 
  __unsafe_unretained NSString *input_url;
  __unsafe_unretained NSString *use_url;  
  __unsafe_unretained NSString *server;
;
struct iOS StructIOS;

ViewController.m:

StructIOS.use_url = @"relay/pincode/apicode/accesskey/1/2/3/99/../900";
NSArray *work_array = [StructIOS.use_url componentsSeparatedByString:@"/"];
StructIOS.server    = [work_array objectAtIndex:0];
if([StructIOS.server length] > 0) 
  NSLog(@">>> 4: %@", StructIOS.server); // OK!!
  StructIOS.server = [StructIOS.server stringByAppendingString:@".***.com"]; // FAIL!!
  NSLog(@">>> 5: %@", StructIOS.server);  

输出:

>>> 4: relay
crash

预期输出:

>>> 5: relay.***.com

编辑:以下方式工作没有崩溃

NSString *fool_ios;

// read from NSString type
StructIOS.server = fool_ios;

// save to NSString type
fool_ios = StructIOS.server;

【问题讨论】:

【参考方案1】:

答案有两个:

不要将对象存储在 Objective-C 结构中。 ARC 不会为他们管理内存。 请勿使用 unsafe_unretained,除非您完全了解它的作用以及您需要它的确切原因。

只需将变量设为类的实例变量即可。这将使它们变得强大,这就是您想要的。

编辑:

请注意,在 Swift 中,将对象存储在 Struct 中是有效的。 Swift 能够在结构中对它们进行内存管理,而 C 则不能。

任何时候编译器强制你使用 __unsafe_unretained,你都可能做错了什么。 (也有例外,但在你的理解水平上,你应该假装 __unsafe_unretained 不存在。)

【讨论】:

【参考方案2】:

为什么它们是 __unsafe_unretailed? componentsSeparatedByString() 可能会在内部创建一些由于使用 __unsafe_unretained 而您没有拥有所有权的子字符串,因此当 componentsSeparatedByString 函数超出范围时它们将被删除。 第 4 行的日志工作纯粹是机会和好运,因为字符串已被释放,但仍然存在于该内存位置。 如果将结构重写为一个简单的类(继承自 NSObject),它应该可以工作。

【讨论】:

i.imgur.com/BfaoqfM.png - 当我删除它时,我得到编译错误:/Users/sun/Desktop/iphone/Objective-C_ios10/ios-demo/Struct.h:11:13: ARC forbids Objective-C objects in struct 其实ARC是禁止在struct中使用objective-c对象的,所以你应该把struct重写为一个简单的类。 OK - 所以它的核心 Objective-C 问题。谢谢你,我会的。 你可能还想做一些事情,比如在 Xcode 设置中启用 malloc scribble 和僵尸,这可以帮助检测到这样的事情(如果你只是在某个地方使用了 StructIOS.server 而没有附加它,你就不会发现这个问题,直到它在某处随机崩溃,malloc scribble 和zombies 等将有助于及早发现它)。这些选项在构建方案中可用。 好的,谢谢。 (当我这样做时很尴尬NSString *fool_ios = [StructIOS.server stringByAppendingString:@".***.com"]; StructIOS.server = fool_ios;

以上是关于Objective-C - 为啥添加两个字符串会导致崩溃?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我base64解码出来的字符串会带乱码

有两个相等的字符串会给出相同的哈希值

在对用户密码进行散列之前添加一个常量字符串会使其更安全吗?

print() 默认是打印完字符串会自动添加一个换行符

如果文本太长,为啥 Snackbar 文本会消失?

sscanf中存在空字符串会报错的问题怎么解决