gpt4 book ai didi

ios - 将保留对象分配给__unsafe_unretained变量,但是为什么它不崩溃?

转载 作者:行者123 更新时间:2023-12-01 19:04:41 26 4
gpt4 key购买 nike

据我所知,str1是在分配后释放的。我只是收到警告,但为什么不崩溃?

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
UIViewController * vc = [[UIViewController alloc] init] ;
self.window.rootViewController = vc ;
[self.window makeKeyAndVisible];

NSString * __unsafe_unretained str1 = [[NSString alloc] initWithFormat:@"First Name: %@", @"cc"] ;
// I think it should crash here !
NSLog(@"string: %u", [str1 length]) ;

NSString * __weak str2 = [[NSString alloc] initWithFormat:@"First Name: %@", @"cc"] ;
// nil for str2
NSLog(@"string: %@", str2) ;

return YES;
}

如果我这样修改代码,可能会很清楚。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
UIViewController * vc = [[UIViewController alloc] init] ;
self.window.rootViewController = vc ;
[self.window makeKeyAndVisible];

NSString * __unsafe_unretained str1 = [[NSString alloc] initWithFormat:@"First Name: %@", @"cc"] ;
// I think it should crash here !
NSLog(@"string: %u", [str1 length]) ;

TestObject * __unsafe_unretained obj1 = [[TestObject alloc] init] ;
NSLog(@"obj1:%@", obj1) ;

return YES;
}

TestObject.m:
@implementation TestObject

- (void)dealloc
{
NSLog(@"%@, %@", NSStringFromSelector(_cmd), self) ;
}

@end

日志是
2013-12-09 15:49:08.625 xxx[23950:a0b] string: 14
2013-12-09 15:49:08.627 xxx[23950:a0b] dealloc, <TestObject: 0x8970ff0>
2013-12-09 15:49:08.627 xxx[23950:a0b] obj1:<TestObject: 0x8970ff0>

最佳答案

那里发生了两种可能的事情。

亚伦·布拉格(Aaron Brager)涵盖了其中的一个-如果对象位于自动释放池中,则该池直到运行循环的下一个周期才会耗尽,因此将为该对象授予临时缓刑。但是,ARC可以取消自动释放的许多实例,并且在这种情况下可以这样做。

因此,答案是内存尚未被覆盖,因此您的通话似乎正常工作。但这只是偶然。如果我们重新排序,我们将得到截然不同的结果:

    NSString * __unsafe_unretained str1 = [[NSString alloc] initWithFormat:@"First Name: %@", @"cc"];

// I think it should crash here !

TestObject * __unsafe_unretained obj1 = [[TestObject alloc] init];
NSLog(@"obj1:%@", obj1);

//oops, crash!
NSLog(@"string: %u", [str1 length]);

在这种情况下,str1指向的内存被分配的TestObject覆盖,因此第一个指针大小的字节从指向NSString的isa更改为TestClass的isa。这意味着要求长度将失败。但是obj1和str1一样无效...该内存现在在空闲列表中,只是在等待重新使用。实际上,它包含随机的垃圾,恰好碰巧是垃圾在重新使用之前似乎是一个有效的Objective-C对象。

如果将长度方法添加到TestClass,我的示例将再次起作用!不要被欺骗... C标准说访问无效的指针是未定义的行为,这意味着编译器可以自由格式化硬盘,删除所有联系人或进行任何操作。它甚至可以在执行程序中的第一条指令之前执行此操作,因为包含未定义操作的程序是完全未定义的。 (直到它做了疯狂的事情之前,它才被定义,但整体上是不确定的)。

因此,简短的版本是:您执行了未定义的操作(访问自由指针),而不是格式化硬盘,编译器决定假装您的程序有意义。那只是编译器优化以及如何使用内存的产物,但是结果就像打印“Hippo”并退出一样没有意义。 (或者更实际地,在启用Zombies仪器和/或保护malloc的情况下运行,您会发现原始代码示例立即崩溃)。

关于ios - 将保留对象分配给__unsafe_unretained变量,但是为什么它不崩溃?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20465128/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com