Objective-C - 为什么添加两个字符串会导致崩溃?
Objective-C - why adding two string is causing the crash?
将新字符串附加到旧字符串导致崩溃。
(如果我这样做会异常工作StructIOS.server = @""; StructIOS.server = [StructIOS.server stringByAppendingString:@".whosebug.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:@".whosebug.com"]; // FAIL!!
NSLog(@">>> 5: %@", StructIOS.server);
}
输出:
>>> 4: relay
crash
预期输出:
>>> 5: relay.whosebug.com
编辑:以下方法没有崩溃
NSString *fool_ios;
// read from NSString type
StructIOS.server = fool_ios;
// save to NSString type
fool_ios = StructIOS.server;
为什么他们是__unsafe_unretailed?
componentsSeparatedByString() 可能会在内部创建一些子字符串,由于使用 __unsafe_unretained,您没有获得这些子字符串的所有权,因此当 componentsSeparatedByString 函数超出范围时,它们将被删除。
第 4 行的日志纯属偶然和好运,因为字符串已被释放,但仍在该内存位置。
如果您将结构重写为简单的 class(继承自 NSObject),它应该可以工作。
答案有两个:
- 不要在 Objective-C 结构中存储对象。 ARC 不会为他们管理内存。
- 不要使用 unsafe_unretained,除非您确切了解它的作用以及您需要它的原因。
只需将您的变量设为 class 的实例变量即可。这将使他们变得强大,这就是你想要的。
编辑:
请注意,在Swift中,将对象存储在结构中是有效的。 Swift 能够在结构中对它们进行内存管理,而 C 则不能。
任何时候编译器强制您使用 __unsafe_unretained,您很可能做错了什么。 (也有例外,但以你的理解水平,你应该假装 __unsafe_unretained 不存在。)
将新字符串附加到旧字符串导致崩溃。
(如果我这样做会异常工作StructIOS.server = @""; StructIOS.server = [StructIOS.server stringByAppendingString:@".whosebug.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:@".whosebug.com"]; // FAIL!!
NSLog(@">>> 5: %@", StructIOS.server);
}
输出:
>>> 4: relay
crash
预期输出:
>>> 5: relay.whosebug.com
编辑:以下方法没有崩溃
NSString *fool_ios;
// read from NSString type
StructIOS.server = fool_ios;
// save to NSString type
fool_ios = StructIOS.server;
为什么他们是__unsafe_unretailed? componentsSeparatedByString() 可能会在内部创建一些子字符串,由于使用 __unsafe_unretained,您没有获得这些子字符串的所有权,因此当 componentsSeparatedByString 函数超出范围时,它们将被删除。 第 4 行的日志纯属偶然和好运,因为字符串已被释放,但仍在该内存位置。 如果您将结构重写为简单的 class(继承自 NSObject),它应该可以工作。
答案有两个:
- 不要在 Objective-C 结构中存储对象。 ARC 不会为他们管理内存。
- 不要使用 unsafe_unretained,除非您确切了解它的作用以及您需要它的原因。
只需将您的变量设为 class 的实例变量即可。这将使他们变得强大,这就是你想要的。
编辑:
请注意,在Swift中,将对象存储在结构中是有效的。 Swift 能够在结构中对它们进行内存管理,而 C 则不能。
任何时候编译器强制您使用 __unsafe_unretained,您很可能做错了什么。 (也有例外,但以你的理解水平,你应该假装 __unsafe_unretained 不存在。)