【问题标题】:Objective-C – Profiling leaks shows Grand Central Dispatch is leakingObjective-C – 分析泄漏显示 Grand Central Dispatch 正在泄漏
【发布时间】:2011-12-23 02:58:15
【问题描述】:

谁能帮我找出泄漏点。我真的不知道我的泄漏在哪里。所以我会在这里发布我的代码,希望有人能帮我发现它。在泄漏工具中,它说责任框架是dispatch_semaphore_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];

        });

    });

【问题讨论】:

    标签: objective-c cocoa-touch memory-leaks grand-central-dispatch


    【解决方案1】:

    由于您是在最外层的异步块中创建一个组,因此您在完成后将组释放到哪里?这是我可以看到您创建的唯一未正确释放的对象。顺便说一句,一个组在幕后创建了一个信号量(所有的调度组实际上是内部调度信号量周围的一些语法糖),这就是仪器以这种方式报告它的原因。

    【讨论】:

      【解决方案2】:

      第零个问题:泄露了什么?

      由于我没有看到扫描您的程序的明显泄漏,因此最有可能出现的问题是:UIKit 对象不是线程安全的,只能从主线程更新,除非它们从另一个线程进入您的程序。

      另请注意NSNotifications 发布在 calling 线程上。

      这意味着你所有的 UIKit 类型的访问和更新都需要在主线程上执行。是的,这可能会导致您应该将其视为未定义行为的泄漏或线程错误。

      【讨论】:

      • 因此,由于我的通知本质上是对“UITableView”和“reloadData”的调用,我应该将“发布通知”调用放在主线程中吗?
      • @Peter 正确。如果您想查看您的程序在调试器中的流程,请将assert([NSThread isMainThread]); 添加到所有直接或间接调用 UIKit 对象的方法(直接消息、属性读取/写入、通知、表重新加载等)。在实践中,如果您确保您的实现是线程安全的并且如果它们没有进入UIKit 对象的实现。另一个常见的误解是atomic_property == thread safe,但它不是线程安全的。
      • 不幸的是,在将调用放入主线程后,我遇到了相同的内存泄漏(Malloc 64 字节)。您在上面看到的代码放在- applicationWillEnterForeground: 中,所以每次我恢复应用程序时都会出现内存泄漏。但是当我想到它的时候。这不是导致内存泄漏的发布通知,因为即使isUpdatedNO,我也会得到泄漏。什么给了?
      • 那是在删除所有 dispatch_/GCD 调用之后?
      • 调度完成回调后需要释放组。
      猜你喜欢
      • 1970-01-01
      • 2011-10-07
      • 2011-06-07
      • 1970-01-01
      • 2023-04-06
      • 2011-06-07
      • 1970-01-01
      相关资源
      最近更新 更多