我是iPhone编程新手。我创建了一个基于Window的应用程序。以下是我的代码:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UILabel *myLabel1 = [[UILabel alloc] initWithFrame:CGRectMake(50, 200, 200, 80)];
myLabel1.text = @"Prasad";
NSLog(@"myLabel retain Count: %d\n", [myLabel1 retainCount]);
[myLabel1 release];
NSLog(@"myLabel retain Count: %d\n", [myLabel1 retainCount]);
[window makeKeyAndVisible];
return YES;
}
Q1。当我发布mylabel1时,在release语句之后的NSLog语句仍然将retainCount打印为1,而理想情况下它应该打印0.此外,应用程序运行正常。
现在考虑以下代码:(除了添加一个NSLog语句之外,它类似于上面的代码:NSLog(@“Bingoooooooo Memeory Released”);)
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UILabel *myLabel1 = [[UILabel alloc] initWithFrame:CGRectMake(50, 200, 200, 80)];
myLabel1.text = @"Prasad";
NSLog(@"myLabel retain Count: %d\n", [myLabel1 retainCount]);
[myLabel1 release];
NSLog(@"Bingoooooooo Memeory Released");
NSLog(@"myLabel retain Count: %d\n", [myLabel1 retainCount]);
[window makeKeyAndVisible];
return YES;
}
现在我的查询是,
1.当我运行上面的代码时,应用程序在打印NSLog后崩溃(@“Bingoooooooo Memeory Released”);为什么应用程序只是通过添加NSLog(@“Bingoooooooo Memeory Released”)语句而崩溃,而在第一个代码中应用程序不会崩溃。
答案 0 :(得分:4)
首先,不要看看retainCount。它不可靠,并受到许多内部因素的影响。代码的第二个版本导致崩溃,因为: 1)您创建一个标签,使其保留计数为1 2)你释放它,使其保留计数为0 3)您向其发送消息。因为它的保留计数为0,所以它已被解除分配,因此应用程序崩溃。
不知道为什么第一个版本不会崩溃
答案 1 :(得分:1)
-retainCount
的文档有以下警告:
重要说明:此方法在调试内存管理问题时通常没有价值。因为任何数量的框架对象可能保留了一个对象以保存对它的引用,而同时自动释放池可能在对象上保留任意数量的延迟版本,所以您不太可能从此获取有用信息方法
而且,正如Stack Overflow关于保留计数的其他各种答案所说,不依赖于-retainCount
。
那说,回答你的问题:
<强> Q1。当我发布mylabel1时,发布语句后面的NSLog语句仍然将retainCount打印为1,而理想情况下它应该打印为0.
让我们考虑您的对象不在自动释放池中。如果对象具有保留计数1并收到release
消息,则将其取消分配。递减释放对象的保留计数的重点是什么?运行时没有这样做,因为它是一个毫无意义的操作,因为对象不再存在。
<强> 1。当我运行上面的代码时,应用程序在打印NSLog后崩溃(@“Bingoooooooo Memeory Released”);为什么应用程序只是通过添加NSLog(@“Bingoooooooo Memeory Released”)声明而崩溃,而在第一个代码中应用程序不会崩溃。
首先,请注意,由于myLabel1
不归其他对象/代码所有,因此在您发送[myLabel1 release]
时会将其释放。如果您向该解除分配的对象发送更多消息(例如[myLabel1 retainCount]
),您的代码可能会崩溃,所以不要这样做。
取消分配对象时,对象占用的内存将标记为可供使用。根据后续指令,可能会或可能不会重写先前由对象占用的内存区域。在重写之前,可以引用解除分配的对象 - 它是一个鬼对象,根本不可靠。在您的情况下,添加另一个NSLog()
指令或其他因素会导致重写该内存区域。