Вызывается dealloc в том же потоке, что и запущенный метод вызывает сбой в зависимости от состояния гонки, это ожидается? - PullRequest
0 голосов
/ 25 декабря 2011

У меня есть объект с именем MadsAdViewController, который запрашивает рекламу асинхронно и вызывается обратно по методу didReceiveResponse.В приложении с большим использованием памяти метод dealloc вызывается очень быстро, а иногда даже тогда, когда метод didReceiveResponse все еще работает.Это приводит к сбоям в результате того, что я бы назвал состоянием гонки.Как показывает вывод, в основном потоке вызываются и didReceiveResponse, и dealloc.

Почему dealloc не ждет завершения метода?И почему блок @synchronized не работает?И как я могу это исправить?

-(void)didReceiveResponse:(MadsAdResponse*) inAdResponse {
    NSLog(@"didReceiveResponse: main thread? = %i, address = %p", [NSThread isMainThread], self);
    @synchronized (self) {
        //... (lots of stuff that takes a while)
        [self logEvent:logAction eventName:EVENT_INIT action:ACTION_VIEW extra:nil];  
    }
    NSLog(@"done with didReceiveResponse response")
}

- (void)dealloc {
    @synchronized (self) {
        NSLog(@"in sync block in dealloc of object %p", self);
        //lots of releases
    }
    [super dealloc]
}

и это вывод:

didReceiveResponse: main thread? = 1, address = 0x139d50b0
in sync block in dealloc of object 0x139d50b0

, а затем приложение вылетает:

*** -[[MadsAdViewController logEvent:eventName:action:extra:]: message sent to deallocated instance 0x139d50b0

1 Ответ

0 голосов
/ 27 декабря 2011

ОК, оказалось хорошим взаимодействием между блоками и этим фрагментом кода, перечисленным выше.

Для контекста, наша библиотека использовалась внешней стороной таким образом, который мы бы не рекомендовали.

Вот что произошло вокруг:

XXXMadsAdViewController *adViewController = [[[XXXMadsAdViewController alloc]init]autorelease];
self.adViewController = adViewController;
[self.adViewController loadAdWithCompletionHandler:^(BOOL success) {
     //stuff
}];

XXXMadsAdViewController оба расширили MadsAdViewController , поскольку он был делегатом для получения вызова метода didReceivePartialAd. [self.delegate didReceivePartialAd] вызывается в методе didReceiveResponse, который я не включил в исходный вопрос, и который назывался до [self logEvent];

Теперь иногда self.adViewController уже был освобожден, но этот блок все еще ждал обратного вызова. При обратном вызове didReceivePartialAd блок был обработан, self.adViewController снова выпущен и приложение упало.

Я исправил проблему, сделав didReceivePartialAd последним оператором метода didReceiveResponse.

Спасибо, ребята, без ваших указателей я бы все еще думал, что это было условие гонки!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...