2-е использование NSURLConnection вызывает iPhone SIGABRT - PullRequest
0 голосов
/ 22 ноября 2010

Я много раз охотился за сообщениями, связанными с NSURLConnection и, в более общем плане, отладкой SIGABRT, но не испытывал радости от этого. Любая помощь с благодарностью.

Итак, при запуске моего приложения пользователю предоставляется вид входа в систему, и при вводе имени пользователя и пароля я запускаю NSURLConnection, выполняя следующие действия в классе LoginService:

-(void)loginWithURLRequest:(NSString*)requestString
{
    if(self.mConnection == nil)
    {
        NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:requestString]
                                                 cachePolicy:NSURLRequestUseProtocolCachePolicy
                                             timeoutInterval:120.0];

        self.mConnection = [[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];
    }
}

-(void)discardLoginDataAndPrepareToReceiveMore
{
    // Releases old mLoginData and assigns a new empty one.
    self.mLoginData = [[NSMutableData alloc] init];
}

-(void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response
{
    [self discardLoginDataAndPrepareToReceiveMore];
}

-(void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data
{
    [mLoginData appendData:data];
}

-(void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error
{
    [self discardLoginDataAndPrepareToReceiveMore];
    [mDelegate onLoginFailure:error];

    self.mConnection = nil;
}

-(void)connectionDidFinishLoading:(NSURLConnection*)connection
{   
    [mDataReader performSelector:mDataReaderSelector withObject:mLoginData];
    [mDelegate onLoggedInSuccessfully];

    self.mConnection = nil;
}

Так что все это прекрасно работает. Проблема в том, что позже я пытаюсь отправить запрос (из другого класса), и вскоре после этого происходит сбой приложения с SIGABRT при загрузке сборки в отдельном потоке, который я не могу отследить до своего кода. Я понимаю, что NSURLConnection запускается в другом потоке и т. Д.

Поэтому я подумал, что, возможно, что-то не так с моим почтовым индексом и заменил его тем же кодом подключения для входа в систему ниже:

    NSString* requestString =  @"identical URL as before in login";

    NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:requestString]
                                             cachePolicy:NSURLRequestUseProtocolCachePolicy
                                         timeoutInterval:120.0];

    self.mConnection = [[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];

Та же проблема, поэтому моя последняя попытка состояла в том, чтобы выяснить, не испортил ли что-то первый логин. то есть, возможно, я ничего не знал о соединениях и не очищал должным образом и т. д. Поэтому я отключил первый вход в систему и оставил свой второй вход, а затем он работает нормально, и я получаю свои обратные вызовы в методах делегата и т. д.

Любые советы о том, что я могу делать неправильно. Кажется, что-то, что я не делаю во время / после установления первого соединения, вызывает сбой второго.

Я могу перешагнуть через 2-й NSURConnection в приложении, когда 1-й логин еще присутствует. Фактический сбой происходит вскоре после того, как приложение продолжает работу после установки этого соединения.

В обоих случаях mConnection является (неатомарным, сохраняемым) свойством каждого класса соответственно.

Я понимаю, что есть более эффективные способы обработки нескольких соединений (после моего поиска), которые мне все равно понадобятся в ближайшее время, но мне нужно, чтобы это сработало для демонстрации для клиента, и мне также любопытно, что Я ошибаюсь, если это подразумевает более фундаментальное недопонимание связей и т. д. с моей стороны

Хм, наверное, мне также не хватает знаний о том, как мне следует отлаживать это. Любые инструменты советы для этого будут оценены. Я избегал использования распределений в инструменте производительности, так как SIGABRT не является проблемой, вызванной утечками, если мое понимание верно?

Дополнительно вот стек вызовов:

- # 0 0x90d7e132 в kill
- # 1 0x90d7e124 в килле $ UNIX2003
- # 2 0x90e108e5 в рейзе
- # 3 0x90e2699c в прерывании
- # 4 0x90d23d35 бесплатно
- # 5 0x026fc081 в __CFStringDeallocate
- # 6 0x026fbccb в _CFRelease
- # 7 0x02720c9d в _CFAutoreleasePoolPop
- # 8 0x0004fe67 in - [NSAutoreleasePool release]
- # 9 0x00300e7f в _UIApplicationHandleEvent
- # 10 0x030c4822 в PurpleEventCallback
- # 11 0x027c5ff4 в __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION

- # 12 0x02726807 в __CFRunLoopDoSource1
- # 13 0x02723a93 в __CFRunLoopRun
- # 14 0x02723350 в CFRunLoopRunSpecific
- # 15 0x02723271 в CFRunLoopRunInMode
- # 16 0x030c300c в GSEventRunModal
- # 17 0x030c30d1 в GSEventRun
- # 18 0x00304af2 в UIApplicationMain
- # 19 0x0000242c в основном на main.m: 14

Я предполагаю, что это означает (когда я также смотрю на мой комментарий ниже), что я не вызываю alloc для чего-то (возможно, строки) перед тем, как выпустить это?

Ответы [ 3 ]

0 голосов
/ 22 ноября 2010

Трудно точно определить без всего источника, но кажется, что вы вызываете второй (и недействительный) релиз для объекта NSString. Посмотрите, как вы обрабатываете строки на протяжении всего проекта. Убедитесь, что они имеют атрибут «copy» в ваших объявлениях свойств, и вы не должны без надобности освобождать те, которые уже автоматически выпущены. (то есть с созданными [NSString stringWithFormat:])

0 голосов
/ 22 ноября 2010

исправлено после включения Zombie (который, я думал, отслеживал только утечки, а не двойные освобождения / авто-релизы). Я автоматически выпускал строку, которая ей не нужна.

Благодаря TomDalling и drowntoge вы оба были на правильном пути. Я только что приехал, а затем увидел ваши ответы (когда я писал это), которые наверняка скоро доставили бы меня туда. Я не знал, что stringWithFormat автоматически освобожден и все равно был автоматически освобожден. Только на самом деле только начал использовать auto release и использовал его для назначения местным жителям и выпуска их после назначения указанного local моим сохраненным свойствам. Что тоже хорошо, просто не очень аккуратно в коде. Я предполагаю, что до этого у меня было много утечек, о которых я не знал. Некоторое время назад я читал документы по памяти, но никогда не использовал авто-релиз, поэтому думаю, что мне нужно вернуться к ним снова: -)

До сих пор понятия не имею, как начальное соединение проявило проблему при включении, так как 2-е соединение довольно давно. Полностью бросил меня, поскольку я думал, что это было все о моем понимании связей. Эта строка была внутри и вокруг этого кода. хмм во всяком случае, ура ребята.

0 голосов
/ 22 ноября 2010

Запустили ли вы ваше приложение с включенными зомби? Возможно, это переиздание, которое подберут зомби.

Еще один способ отследить это - включить историю malloc и проверить, откуда исходит плохой указатель (0x818c0b0 в вашем комментарии).

Это может быть полезно для вас: iPhone - ошибки отладки "освободившийся указатель не выделен" ошибки

Похоже, что память повреждена внутри CFString / NSString объекта, что означает, что он может происходить где-то, что выглядит совершенно не связанным. Вы можете передавать неверный указатель в NSString, поэтому вы можете проверить это тоже.

Кроме того, каково значение mDataReaderSelector? Если вы делаете performSelector:, и метод возвращает структуру (например, NSRect), которая может повредить память. Это длинный выстрел, но я все равно решил проверить.

...