У меня есть небольшое приложение, которое загружает цены на акции и работает отлично (в течение многих лет) до моего недавнего обновления до 10.5.7. После обновления программа выйдет из строя при этом вызове:
NSString *currinfo = [NSString stringWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://finance.yahoo.com/d/quotes.csv?s=%@&f=l1c1p2", escsymbol]]];
Как ни странно, крушение не происходит сразу. Эта строка кода вызывается много раз, без проблем, а затем программа в итоге выходит из строя через 1-2 часа из-за сбоя в этом вызове.
У меня первоначально был длинный пост, описывающий мои попытки исследовать эту проблему. Я получил два предложения: (i) сделать асинхронный вызов (возможно, в любом случае лучше) и (ii) использовать NSZombieEnabled, чтобы исследовать возможность того, что объект Objective-C будет освобожден раньше (этот комментарий был сделан в ответ на следы стека, показывающие сбой в objc_msgSend).
Я потратил много времени на то, чтобы сделать асинхронный вызов (используя [[NSURLConnection alloc] initWithRequest: theRequest delegate: self]), и это не помогло. Программа по-прежнему не срабатывала в конце концов, обычно через 10-15 минут. В течение этого интервала перед сбоем многие асинхронные вызовы были сделаны без каких-либо проблем, данные были возвращены и т.д. Все было в порядке. Затем программа снова разбилась.
Затем я включил NSZombieEnabled. Разумеется, когда программа в конечном итоге потерпела крах, я получил сообщение:
-[CFArray count]: message sent to deallocated instance 0x16b90bd0
"info malloc 0x16b90bd0" затем дал:
0: 0x93db810c in malloc_zone_malloc
1: 0x946bc3d1 in _CFRuntimeCreateInstance
2: 0x9464a138 in __CFArrayInit
3: 0x946cd647 in _CFStreamScheduleWithRunLoop
4: 0x932d1267 in _Z16_scheduleRStreamPKvPv
5: 0x946bf15c in CFSetApplyFunction
6: 0x932b0e2b in CFNSchedulingSetScheduleReadStream
7: 0x9331a310 in _ZN12HTTPProtocol19createAndOpenStreamEv
8: 0x9332e877 in _ZN19URLConnectionLoader24loaderScheduleOriginLoadEPK13_CFURLRequest
9: 0x9332d739 in _ZN19URLConnectionLoader26LoaderConnectionEventQueue33processAllEventsAndConsumePayloadEP20XConnectionEventInfoI12XLoaderEvent18XLoaderEventParamsEl
10: 0x9332dbdd in _ZN19URLConnectionLoader13processEventsEv
11: 0x932d8dbf in _ZN17MultiplexerSource7performEv
12: 0x946ba595 in CFRunLoopRunSpecific
13: 0x946bac78 in CFRunLoopRunInMode
14: 0x9058c530 in +[NSURLConnection(NSURLConnectionReallyInternal) _resourceLoadLoop:]
15: 0x90528e0d in -[NSThread main]
16: 0x905289b4 in __NSThread__main__
17: 0x93de8155 in _pthread_start
18: 0x93de8012 in thread_start
Я не эксперт в чтении стеков стека, но разве эта трассировка не указывает на проблему в коде Apple, а не на мой код? Или я могу как-то нести ответственность за де-распределение рассматриваемого CFArray? Есть ли способ для дальнейшего изучения причины проблемы?
(Здесь остальная часть моего первоначального сообщения)
Увидев, что stringWithContentsOfURL
устарел, я переключился на этот код:
pathURL = [NSURL URLWithString:[NSString stringWithFormat:@"http://finance.yahoo.com/d/quotes.csv?s=%@&f=l1c1p2", escsymbol]];
NSURLRequest *request = [NSURLRequest requestWithURL:pathURL cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:30.0];
responseData = [ NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *currinfo = nil;
if ([error code]) { dNSLog((@"%@ %d %@ %@ %@", [ error domain], [ error code], [ error localizedDescription], request, @"file://localhost/etc/gettytab")); }
Это не помогло. Программа по-прежнему выходит из строя в строке sendSynchronousRequest
через произвольный промежуток времени, с этой информацией в отладчике:
0 0x93db7286 in mach_msg_trap
1 0x93dbea7c in mach_msg
2 0x946ba04e in CFRunLoopRunSpecific
3 0x946bac78 in CFRunLoopRunInMode
4 0x932b53eb in CFURLConnectionSendSynchronousRequest
5 0x905dca4b in +[NSURLConnection sendSynchronousRequest:returningResponse:error:]
... и т.д..
Реальная авария может быть в другом потоке:
0 libobjc.A.dylib 0x965c3688 objc_msgSend + 24
1 com.apple.CoreFoundation 0x946cc581 _CFStreamSignalEventSynch + 193
2 com.apple.CoreFoundation 0x946ba595 CFRunLoopRunSpecific + 3141
3 com.apple.CoreFoundation 0x946bac78 CFRunLoopRunInMode + 88
4 com.apple.Foundation 0x9058c530 +[NSURLConnection(NSURLConnectionReallyInternal) _resourceLoadLoop:] + 320
5 com.apple.Foundation 0x90528e0d -[NSThread main] + 45
6 com.apple.Foundation 0x905289b4 __NSThread__main__ + 308
7 libSystem.B.dylib 0x93de8155 _pthread_start + 321
8 libSystem.B.dylib 0x93de8012 thread_start + 34
который, как я полагаю, является нитью, порожденной для загрузки URL-адреса. Кстати, код обработки ошибок работает нормально - когда я намеренно вызывают ошибку, отключаясь от Интернета, сообщение об ошибке сообщается только в консоли, и программа не сбой.
Это невероятно расстраивает. Я был бы очень рад потратить столько времени, сколько необходимо, чтобы выявить проблему, но я как бы не согласен с моими знаниями с gdb и особенно с ассемблером. Я не знаю, как узнать, какова фактическая проблема для кода Foundation. Сначала я подумал, что, возможно, autoreleased NSString escsymbol
как-то освобождается, но отправка его сообщения сохранения не помогло. Если бы это было так, как я мог это доказать?
Есть ли у кого-нибудь еще эта проблема?