2013-04-10 19 views
9

Miałem dzisiaj dość interesującą awaria exc_bad_access. Po wielu kopaniu wymyśliłem następujące informacje (działające w symulatorze):W jaki sposób NSLog może spowodować awarię kodu?

Jeśli po prostu uruchomiłem kod, aplikacja losowo ulegał awarii w losowym punkcie podczas ładowania danych do mojego zarządzanego obiektu. Z tego, co mogłem powiedzieć, to zawsze się zawieszało, gdy ładowałem dane do zarządzanego obiektu - nie na przekroje przekształcone z mojego Dysku JSON na dane do faktycznie używanego obiektu (od łańcuchów i NSNulls do ints/floats i nils)

Losowe awarie są oczywiście złe, więc próbowałem przejść przez proces w debugerze, ale to nie okazało się praktyczne - przetwarzałem wiele obiektów, więc przechodziłem między nimi jeden po drugim po prostu nie działa. Postanowiłem więc dodać trochę NSLogów, aby śledzić proces i spróbować rozpoznać wzór w ten sposób.

Natychmiastowe rozwiązanie awarii.

Tylko jeden NSLog, w dowolnym miejscu procesu, zapobiegał awariom.

W końcu śledziłem drogę do stosu i znalazłem faktyczny problem: uzyskiwałem dostęp do zarządzanego obiektu w środowisku gwintowanym, ale NIE z powiązanej metody performBlockAndWait: MOC. W tym momencie katastrofa była dla mnie niesamowicie oczywista - jestem zszokowany, że wcześniej nie miałem więcej problemów. Mogę się założyć, że pomiędzy posiadaniem "małego" zestawu danych testowych 2-3 obiektów i posiadającego kod debugowania z NSLogs, błąd został dość skutecznie zamaskowany wcześniej ... ale pozostaje pytanie:

Dlaczego czy NSLog zapobiega awarii aplikacji? Jak na Ziemi fragment kodu bez efektów ubocznych może zmienić wykonanie reszty aplikacji? To nie ma sensu!

+0

czy używasz w dowolnym miejscu performSelector: method i selektor, który zwraca parametr id id, nie jako parametr? Czasami NSLog może zapobiegać błędom spowodowanym tymi błędami.W takim przypadku trzeba użyć NSInvocation – BergP

Odpowiedz

12

Co zadziwiające, jest to dość powszechna sytuacja: widziałem ją więcej niż raz, gdy włączenie logowania w miejscu, które nie ma związku z innymi, natychmiast rozwiązałoby problem z czasem w innym miejscu.

Powodem jest to, że NSLog, podobnie jak wiele innych funkcji wyjściowych, ma wewnętrzną synchronizację. Istnieje gdzieś muteks, który chroni dostęp do wewnętrznych buforów NSLog sam w sobie lub w jednej z bibliotek I/O, których używa. Ta synchronizacja umożliwia dzwoniącym używanie NSLog z wielu wątków. Właśnie ta synchronizacja zmienia czas twojego programu, wpływając na warunki wyścigu i ostatecznie rozwiązując problem.

+0

Nie wiedziałem o tym, ładny, +1 .. Po prostu wow. –

+0

Nigdy nawet nie myślałem o tej możliwości, ale myślę, że to może spowodować ogromne zmiany w sposobie działania mojego kodu. Cool: – RonLugge

+1

@RonLugge Nasz cały zespół został oszołomiony, kiedy dokonaliśmy tego odkrycia po raz pierwszy: otrzymaliśmy raporty o częstych losowych awariach z jednej z naszych zainstalowanych witryn, poprosiliśmy ich o zmianę poziomów logowania z "error" na "debugowanie ", i wyślij nam logi, kiedy wrócili do nas z odpowiedzią, że gdy tylko pojawią się na poziomach dziennika, nie będą już mogli odtworzyć katastrofy, nie uwierzyliśmy im na początku, ale kiedy wyłączyliśmy wylogowanie (był zawsze "na" w rozwoju), sami powtórzyliśmy katastrofę :) – dasblinkenlight

3

Dlaczego NSLog zapobiega awariom aplikacji? W jaki sposób na ziemi kod bez efektów ubocznych może zmienić wykonanie reszty aplikacji na ? To nie ma sensu!

Rzeczywiście ma to sens. Naprawdę.

Pojedynczyma na celu wydrukowanie czegoś na konsolę, zajmuje kilka ułamków sekundy, a pomiędzy przetwarzaniem na coś się kończy, a awaria (może wynikać z braku dostępności danych wejściowych) nie więcej.

Twój błąd może wynikać z połączenia asynchronicznego. Twój następny proces rozpocznie się przed ukończeniem poprzedniego. A twój następny proces wymaga danych z procesu previos. NSLog zajmuje trochę czasu.

+0

Podczas gdy myślałem o tym, nie miało to dla mnie sensu w tym kontekście - podczas gdy mogę być w środowisku wielowątkowym, tylko jedna "kopia" tego kodu działałaby pod dowolnym czas (więc mam "główny wątek" i "wątek danych"). Cokolwiek powoduje, że zarządzane obiekty nie są bezpieczne, nie powinno być wykonywane przez NSLog ... pomyślałem. – RonLugge

+0

Spotykam się z nimi dość regularnie :( –

Powiązane problemy