Objective c 目标-C–;分析泄漏显示Grand Central Dispatch正在泄漏
有人能帮我找出漏洞吗。我真的不知道我的漏洞在哪里。所以我会在这里发布我的代码,希望有人能帮我发现它。在泄漏工具中,它说负责的帧是我没有调用的Objective c 目标-C–;分析泄漏显示Grand Central Dispatch正在泄漏,objective-c,cocoa-touch,memory-leaks,grand-central-dispatch,Objective C,Cocoa Touch,Memory Leaks,Grand Central Dispatch,有人能帮我找出漏洞吗。我真的不知道我的漏洞在哪里。所以我会在这里发布我的代码,希望有人能帮我发现它。在泄漏工具中,它说负责的帧是我没有调用的dispatch\u semaphore\u create dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [[UIApplication sharedApplication] setNetworkActivityIndicat
dispatch\u semaphore\u create
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if ([defaults boolForKey:@"notFirstRunSeminars"]) {
BOOL isUpdated = self.seminarsParser.seminarsAreUpdated;
if (isUpdated) {
DLog(@"Seminars have been updated");
[[NSNotificationCenter defaultCenter]
postNotificationName:@"updateSeminarsTable"
object:nil];
[[[[[self tabBarController] tabBar] items] objectAtIndex:kSeminarsTabIndex] setBadgeValue:self.seminarsParser.numberOfNewSeminars];
self.seminarsParser.numberOfNewSeminars = nil;
}
}
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if ([defaults boolForKey:@"notFirstRunCareers"]) {
BOOL isUpdated = self.careersParser.careersAreUpdated;
if (isUpdated) {
DLog(@"Careers have been updated");
[[NSNotificationCenter defaultCenter]
postNotificationName:@"updateCareersTable"
object:nil];
[[[[[self tabBarController] tabBar] items] objectAtIndex:kCareersTabIndex] setBadgeValue:self.careersParser.numberOfNewCareers];
self.careersParser.numberOfNewCareers = nil;
}
}
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if ([defaults boolForKey:@"notFirstRunOffices"]) {
BOOL isUpdated = [officesParser officesAreUpdated];
if (isUpdated) {
DLog(@"Offices have been updated");
[[NSNotificationCenter defaultCenter]
postNotificationName:@"updateOfficesTable"
object:nil];
}
}
});
dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
});
});
零问题:泄露了什么 由于我在扫描您的程序时没有看到明显的泄漏,因此最可能的问题是:UIKit对象不是线程安全的,只能从主线程更新,除非它们从另一个线程进入您的程序 还要注意,
NSNotification
s被发布在调用线程上
这意味着所有UIKit类型的访问和更新都需要在主线程上执行。是的,它会引入泄漏或线程错误,你应该把它看作是未定义的行为。
零问题:什么是泄露?
由于我在扫描您的程序时没有看到明显的泄漏,因此最可能的问题是:UIKit对象不是线程安全的,只能从主线程更新,除非它们从另一个线程进入您的程序 还要注意,NSNotification
s被发布在调用线程上
这意味着所有UIKit类型的访问和更新都需要在主线程上执行。是的,这可能会导致泄漏或线程错误,你应该把它们看作是未定义的行为。 在你完成它之后,你在哪里释放组,因为你在最外面的异步块中创建了一个组?这是我能看到你创建的唯一一个没有被正确释放的对象。顺便说一句,一个组在幕后创建了一个信号量(调度组实际上就是内部调度信号量周围的一些语法糖),这就是instruments以这种方式报告它的原因。既然您在最外层的异步块中创建了一个组,那么在处理完组后,您在哪里释放它?这是我能看到你创建的唯一一个没有被正确释放的对象。顺便说一句,一个组在幕后创建了一个信号量(调度组实际上只是内部调度信号量周围的一些语法糖),这就是instruments以这种方式报告它的原因。因此,由于我的通知本质上是对“UITableView”的调用以“reloadData”,我应该把“post notification”放在主线程中的调用?@Peter正确。如果要查看程序在调试器中的流动情况,请添加
assert([NSThread isMainThread])
调用所有直接或间接调用UIKit对象(直接消息、属性读/写、通知、表重新加载等)的方法。实际上,如果您确保您的实现是线程安全的,并且没有进入UIKit对象的实现,则可以向UIKit对象发送消息以访问您的实现/属性。另一个常见的误解是atomic_property==thread safe
,但它不是threadsafe。不幸的是,在将调用放在主线程中之后,我得到了相同的内存泄漏(Malloc 64字节)。上面看到的代码放在-applicationWillEnterForeground:
中,因此每次我恢复应用程序时,都会出现内存泄漏。但是当我想到它的时候。不是发布通知导致内存泄漏,因为即使isUpdated
是NO
,我也会收到泄漏。给出了什么?这是在删除所有分派\uucode>/GCD调用之后?您需要在安排完成回调后释放组。因此,由于我的通知本质上是对“UITableView”的调用,以“reloadData”,我应该将“post notification”调用放在主线程中。@Peter Correct。如果要查看程序在调试器中的流动情况,请添加assert([NSThread isMainThread])
调用所有直接或间接调用UIKit对象(直接消息、属性读/写、通知、表重新加载等)的方法。实际上,如果您确保您的实现是线程安全的,并且没有进入UIKit对象的实现,则可以向UIKit对象发送消息以访问您的实现/属性。另一个常见的误解是atomic_property==thread safe
,但它不是threadsafe。不幸的是,在将调用放在主线程中之后,我得到了相同的内存泄漏(Malloc 64字节)。上面看到的代码放在-applicationWillEnterForeground:
中,因此每次我恢复应用程序时,都会出现内存泄漏。但是当我想到它的时候。不是发布通知导致内存泄漏,因为即使isUpdated
是NO
,我也会收到泄漏。给出了什么?这是在删除所有的分派\ucode>/GCD调用之后?您需要在安排完成回调后释放组。