Podczas wdrażania aplikacji na urządzeniu program zostanie zamknięty po kilku cyklach z następującym błędem:
Program received signal: "EXC_BAD_ACCESS".
Program działa bez żadnych problemów na symulatorze iPhone'a, będzie także debugował i działał, o ile krok po kroku wykonam instrukcje. Jak tylko pozwolę, by znów zaczął działać, uderzę w EXC_BAD_ACCESS
sygnał.
W tym konkretnym przypadku był to błąd w kodzie akcelerometru. Nie wykonałby się w symulatorze, dlatego nie wyrzucił żadnych błędów. Jednak wykona się po wdrożeniu na urządzeniu.
Większość odpowiedzi na to pytanie dotyczy EXC_BAD_ACCESS
błędu ogólnego , więc pozostawię to otwarte jako rozwiązanie problemu przerażającego błędu Bad Access.
EXC_BAD_ACCESS
jest zwykle wyrzucany w wyniku nielegalnego dostępu do pamięci. Więcej informacji znajdziesz w odpowiedziach poniżej.
Czy napotkałeś już EXC_BAD_ACCESS
wcześniej sygnał i jak sobie z nim poradziłeś?
źródło
Główną przyczyną EXC_BAD_ACCESS jest próba dostępu do uwolnionych obiektów.
Aby dowiedzieć się, jak rozwiązać ten problem, przeczytaj ten dokument: DebuggingAutoReleasePool
Nawet jeśli nie uważasz, że „wypuszczasz automatycznie zwalniane obiekty”, dotyczy to ciebie.
Ta metoda działa wyjątkowo dobrze. Używam go cały czas z wielkim sukcesem !!
Podsumowując, wyjaśnia to, jak używać klasy debugowania NSZombie Cocoa i narzędzia wiersza polecenia „malloc_history”, aby znaleźć dokładnie to, co zostało zwolnione w twoim kodzie.
Dygresja:
Uruchamianie instrumentów i sprawdzanie wycieków nie rozwiąże problemu EXC_BAD_ACCESS. Jestem pewien, że wycieki pamięci nie mają nic wspólnego z EXC_BAD_ACCESS. Definicja wycieku jest obiektem, do którego nie masz już dostępu i dlatego nie możesz go nazwać.
AKTUALIZACJA: Teraz używam instrumentów do debugowania wycieków. W Xcode 4.2 wybierz Produkt-> Profil, a po uruchomieniu Instruments wybierz „Zombie”.
źródło
Sygnał EXC_BAD_ACCESS jest wynikiem przekazania nieprawidłowego wskaźnika do wywołania systemowego. Dostałem je dzisiaj już wcześniej z programem testowym na OS X - przekazałem niezainicjowaną zmienną do
pthread_join()
, co było spowodowane wcześniejszą literówką.Nie znam rozwoju iPhone'a, ale powinieneś dokładnie sprawdzić wszystkie wskaźniki bufora przekazywane do wywołań systemowych. Całkowicie podnieś poziom ostrzegawczy kompilatora (w gcc użyj opcji
-Wall
i-Wextra
). Włącz jak najwięcej diagnostyki na symulatorze / debuggerze.źródło
Z mojego doświadczenia wynika, że jest to na ogół spowodowane nielegalnym dostępem do pamięci. Sprawdź wszystkie wskaźniki, zwłaszcza wskaźniki obiektów, aby upewnić się, że zostały zainicjowane. Upewnij się, że plik MainWindow.xib, jeśli go używasz, jest poprawnie skonfigurowany i zawiera wszystkie niezbędne połączenia.
Jeśli żadne z tych sprawdzeń na papierze niczego nie wykryje, a nie stanie się to podczas wykonywania pojedynczych kroków, spróbuj zlokalizować błąd za pomocą instrukcji NSLog (): posyp je kodem, przesuwając je, dopóki nie wyodrębnisz linii, która powoduje błąd. Następnie ustaw punkt przerwania w tej linii i uruchom program. Kiedy osiągniesz punkt przerwania, sprawdź wszystkie zmienne i zawarte w nich obiekty, aby sprawdzić, czy coś nie wygląda tak, jak się spodziewasz. Zwłaszcza zwracam uwagę na zmienne, których klasy obiektów jest coś, czego się nie spodziewałeś. Jeśli zmienna ma zawierać UIWindow, ale zamiast tego zawiera NSNotification, ten sam podstawowy kod błędu może objawiać się w inny sposób, gdy debugger nie działa.
źródło
Właśnie spędziłem kilka godzin na śledzeniu EXC_BAD_ACCESS i odkryłem, że NSZombies i inne środowiska env nie wydają mi się nic powiedzieć.
Dla mnie była to głupia instrukcja NSLog ze specyfikatorami formatu, ale nie przekazano żadnych argumentów.
Naprawione przez
źródło
Filmy WWDC z 2010 r. Są dostępne dla wszystkich uczestników programu dla programistów Apple. Jest świetny film: „Sesja 311 - Zaawansowana analiza pamięci z instrumentami”, który pokazuje kilka przykładów używania zombie w instrumentach i debugowania innych problemów z pamięcią.
Aby uzyskać link do strony logowania, kliknij TUTAJ .
źródło
Nie jest to kompletna odpowiedź, ale jedna konkretna sytuacja, w której ją otrzymałem, dotyczy próby uzyskania dostępu do obiektu, który „zmarł”, ponieważ próbowałem użyć funkcji automatycznego uwalniania:
Tak więc na przykład przekazałem to jako obiekt do „powiadomienia” (zarejestrowałem go jako słuchacza, obserwatora, dowolny idiom, który ci się podoba), ale już umarł po wysłaniu powiadomienia i otrzymam EXC_BAD_ACCESS. Zmiana
[[MyNetObject alloc] init]
i późniejsze zwolnienie w razie potrzeby rozwiązało błąd.Innym powodem może być na przykład przekazanie obiektu i próba jego zapisania:
Później podczas próby uzyskania dostępu do myObjectDefinedInHeader możesz mieć problemy. Za pomocą:
może być tym, czego potrzebujesz. Oczywiście to tylko kilka przykładów tego, na co wpadłem i są też inne powody, ale mogą one okazać się nieuchwytne, więc o nich wspomnę. Powodzenia!
źródło
Aby dodać inną sytuację, w której może się to zdarzyć:
Miałem kod:
Oczywiście zapomniałem przydzielić pamięć dla ciągu:
naprawia problem.
źródło
Inną metodą wychwytywania wyjątków EXC_BAD_ACCESS przed ich wystąpieniem jest analizator statyczny w XCode 4+.
Uruchom analizator statyczny za pomocą opcji Produkt> Analizuj (shift + cmd + B). Kliknięcie dowolnego komunikatu wygenerowanego przez analizator spowoduje nałożenie na źródło diagramu pokazującego sekwencję zatrzymań / zwolnień obiektu naruszającego prawo.
źródło
Uważam, że warto ustawić punkt przerwania na objc_exception_throw. W ten sposób debugger powinien się zepsuć, gdy pojawi się EXC_BAD_ACCESS.
Instrukcje można znaleźć tutaj Techniki debugowania
źródło
Zastosuj prostą zasadę „jeśli nie przydzieliłeś go lub nie zatrzymałeś, nie zwalniaj”.
źródło
Jak debugować EXC_BAD_ACCESS
Sprawdź powyższy link i postępuj zgodnie z instrukcją .... Kilka szybkich instrukcji dotyczących używania NSZombies
Uruchom aplikację i po jej awarii (powinien wyświetlać „Przerwany” zamiast „EXC_BAD_ACCESS” ... sprawdź konsolę (Uruchom> konsolę) ... powinien pojawić się komunikat informujący, do którego obiektu próbuje uzyskać dostęp.
-Ben
źródło
Debugowałem i refaktoryzowałem kod, aby rozwiązać ten błąd przez ostatnie cztery godziny. Post powyżej pokazał mi problem:
Właściwość przed: startPoint = [[przydział DataPoint] init]; startPoint = [DataPointList objectAtIndex: 0];
. . . x = startPoint.x - 10; // EXC_BAD_ACCESS
Właściwość po: startPoint = [[przydział DataPoint] init]; startPoint = [[DataPointList objectAtIndex: 0] zachowaj];
Do widzenia EXC_BAD_ACCESS
źródło
Mam nadzieję, że po zakończeniu zwalniasz „sznurek”!
źródło
Zapomniałem zwrócić siebie w metodzie init ...;)
źródło
To jest doskonały wątek. Oto moje doświadczenie: pomyliłem się ze słowem kluczowym zachowaj / przypisaj w deklaracji właściwości. Powiedziałem:
gdzie powinienem był powiedzieć
źródło
EXC_BAD_ACCESS napotkałem na iPhonie tylko podczas próby wykonania metody C zawierającej dużą tablicę. Symulator był w stanie zapewnić mi wystarczającą ilość pamięci, aby uruchomić kod, ale nie urządzenie (tablica miała milion znaków, więc była odrobinę za duża!).
EXC_BAD_ACCESS wystąpił tuż po punkcie wejścia metody i przez pewien czas byłem zdezorientowany, ponieważ nie było go w pobliżu deklaracji tablicy.
Być może ktoś inny mógłby skorzystać z moich kilku godzin ciągnięcia włosów.
źródło
Zapomniałem wyjąć z nieprzydzielonego wskaźnika
dealloc
. Otrzymywałem exc_bad_access na moim rootView UINavigationController, ale tylko czasami. Zakładałem, że problem tkwi w rootView, ponieważ ulegał awarii w połowie jego viewDidAppear {}. Okazało się, że stało się to dopiero po tym, jak opublikowałem widok złym wydaniem dealloc {} i to było to!„EXC_BAD_ACCESS” [Przełączanie na proces 330] Brak dostępnej pamięci do zaprogramowania: niebezpieczne połączenie z centrum handlowym
Myślałem, że to problem, w którym próbowałem przydzielić ... a nie tam, gdzie próbowałem zwolnić non-przydział, D'oh!
źródło
Jak radzę sobie z EXC_BAD_ACCESS
Czasami czuję, że kiedy zostanie zgłoszony błąd EXC_BAD_ACCESS, xcode wyświetli błąd w klasie main.m, nie podając żadnych dodatkowych informacji o tym, gdzie dochodzi do awarii (czasami).
W tych czasach możemy ustawić wyjątkowy punkt przerwania w Xcode, aby po wychwyceniu wyjątku został umieszczony punkt przerwania i bezpośrednio poinformować użytkownika o awarii w tej linii
źródło
Wywołania NSAssert () w celu sprawdzenia parametrów metody są bardzo przydatne do śledzenia i unikania przekazywania zer.
źródło
Właśnie miałem ten problem. Dla mnie powodem było usunięcie obiektu zarządzanego przez CoreData i próba odczytania go później z innego miejsca.
źródło
Debugowałem i refaktoryzowałem kod, aby rozwiązać ten błąd przez ostatnie cztery godziny. Post powyżej pokazał mi problem:
Nieruchomość przed:
Nieruchomość po:
Do widzenia
EXC_BAD_ACCESS
Dziękuję bardzo za odpowiedź. Walczę z tym problemem przez cały dzień. Jesteś niesamowity!
źródło
Tylko dodać
Lynda.com ma fantastyczne DVD o nazwie
a rozdział 6, lekcja 3 dotyczy EXEC_BAD_ACCESS i pracy z zombie.
Wspaniale było mi zrozumieć, nie tylko kod błędu, ale jak mogę użyć Zombie, aby uzyskać więcej informacji na temat uwolnionego obiektu.
źródło
Aby sprawdzić, jaki może być błąd
Użyj NSZombieEnabled.
Aby aktywować funkcję NSZombieEnabled w aplikacji:
Wybierz Projekt> Edytuj aktywny plik wykonywalny, aby otworzyć okno informacji o pliku wykonywalnym. Kliknij Argumenty. Kliknij przycisk dodaj (+) w sekcji „Zmienne do ustawienia w środowisku”. Wpisz NSZombieEnabled w kolumnie Nazwa i YES w kolumnie Wartość. Upewnij się, że zaznaczono pole wyboru dla pozycji NSZombieEnabled.
Znalazłem tę odpowiedź na iPhoneSDK
źródło
Zdaję sobie sprawę, że o to pytano jakiś czas temu, ale po przeczytaniu tego wątku znalazłem rozwiązanie dla XCode 4.2: Produkt -> Edytuj schemat -> Karta diagnostyczna -> Włącz obiekty zombie
Pomógł mi znaleźć wiadomość wysyłaną do zwolnionego obiektu.
źródło
Jeśli masz nieskończoną rekurencję, myślę, że możesz również mieć ten błąd. To był przypadek dla mnie.
źródło
Jeszcze inna możliwość: przy użyciu bloków w kolejkach może się łatwo zdarzyć, że spróbujesz uzyskać dostęp do obiektu w innej kolejce, który został już w tej chwili zwolniony. Zazwyczaj, gdy próbujesz wysłać coś do GUI. Jeśli punkt przerwania wyjątku jest ustawiony w dziwnym miejscu, może to być przyczyna.
źródło
Mam to, ponieważ nie używałem
[self performSegueWithIdentifier:sender:]
i-(void) prepareForSegue:(UIstoryboardSegue *)
dobrzeźródło
Nie zapominaj o
@
symbolu podczas tworzenia ciągów, traktując to,C-strings
coNSStrings
spowodujeEXC_BAD_ACCESS
.Użyj tego:
Zamiast tego:
PS - zwykle przy zapełnianiu zawartości
array
dużą ilością rekordów.źródło
XCode 4 i nowsze wersje, dzięki Instrumentom, stało się to naprawdę proste. Wystarczy uruchomić Zombie w Instrumentach. W tym samouczku wyjaśniono to dobrze: debugowanie instrumentów exc_bad_access xcode
źródło