Programuję aplikację w Objective-C i otrzymuję ten błąd:
MyApp (2121,0xb0185000) malloc: *** błąd dla obiektu 0x1068310: podwójne wolne
*** ustaw punkt przerwania w malloc_error_break do debugowania
Dzieje się tak, gdy wypuszczam NSAutoreleasePool i nie mogę dowiedzieć się, który obiekt dwukrotnie wypuszczam.
Jak ustawić jego punkt przerwania?
Czy istnieje sposób, aby dowiedzieć się, co to jest ten „obiekt 0x1068310”?
Odpowiedzi:
Dowiesz się, czym jest obiekt, gdy włamiesz się do debugera. Wystarczy spojrzeć na stos wywołań, a znajdziesz miejsce, w którym go uwolnisz. To powie ci, który to jest obiekt.
Najłatwiejszym sposobem ustawienia punktu przerwania jest:
źródło
Gdy obiekt jest „podwójnie zwalniany”, najczęstszą przyczyną jest to, że (niepotrzebnie) zwalniasz obiekt, który jest automatycznie zwalniany, a później jest on automatycznie zwalniany, gdy zawierająca pula autowywolnienia zostanie opróżniona.
Odkryłem, że najlepszym sposobem na śledzenie dodatkowego wydania jest użycie zmiennej środowiskowej NSZombieEnabled dla pliku wykonywalnego, którego dotyczy problem, w Xcode. Aby dowiedzieć się, jak z niego korzystać, odwiedź tę stronę wiki CocoaDev . (Oprócz tej strony firma Apple udokumentowała kilka niewiarygodnie mało znanych, ale przydatnych wskazówek dotyczących debugowania kodu w Xcode, z których niektóre pozwoliły zaoszczędzić mój bekon więcej niż kilka razy. Proponuję zapoznać się z tą uwagą techniczną na developer.apple.com - link przeskakuje do sekcji dotyczącej frameworka Cocoa's Foundation).
Edycja: Często możesz wyśledzić obraźliwy obiekt w debugerze Xcode, ale często jest to znacznie łatwiejsze, jeśli używasz Instruments do pomocy. W Xcode wybierz Uruchom → Uruchom z Performance Tool → Object Alocations i powinieneś być w stanie prześledzić problematyczny obiekt z powrotem do miejsca, w którym został utworzony. (Działa to najlepiej, jeśli masz włączone zombie, jak omówiono powyżej). Uwaga: Snow Leopard dodaje narzędzie Zombie do instrumentów, dostępne również z menu Uruchom. Samo może być warte 29 $! ;-)
Jest tu również powiązane pytanie SO .
źródło
Chcę tylko dodać moje doświadczenie jako dodatek do odpowiedzi Quinna Taylora.
W jednej z moich aplikacji muszę analizować i zapisywać dane w podstawowych obiektach danych, a później wyświetlać te obiekty w widokach. W rzeczywistości aplikacja działa dobrze i wcale się nie zawiesza, dopóki nie próbowałem wykonać testu warunków skrajnych, aby wielokrotnie nawigować tam iz powrotem, próbowałem otworzyć wiele widoków tak szybko, jak to możliwe. Aplikacja ulega awarii z powyższym komunikatem.
Wypróbowałem wszystkie metody, które zasugerował Quinn w swojej odpowiedzi i nadal nie udało mi się ustalić, gdzie jest dokładna przyczyna.
Ustawiłem NSZombieEnabled = YES i NSStackLogging = YES, uruchomiłem powłokę poleceń malloc_history, aby dowiedzieć się, dlaczego, ale nadal nie mam szczęścia. Zawsze wskazuje miejsce, w którym zapisuję dane w podstawowych obiektach danych, w rzeczywistości sprawdzałem tysiące razy ponad zwolnione obiekty, nic dziwnego.
Uruchomienie w instrumentach z różnymi narzędziami (alokacje, wycieki itp.) Nadal nie pomogło. Włącz Guard Malloc nadal nic nie ma.
Ostateczna ratunek: próbowałem wrócić do widoków, w których obiekty zostały zabrane z danych podstawowych i wysłałem wiadomość o zachowaniu do wszystkich tych obiektów oraz odnotowałem te zmiany. To rozwiązało problem !!!
Więc dowiedziałem się, że nie udało mi się jednego zachować, to jest dokładnie przyczyna. Chcę tylko podzielić się moim doświadczeniem, aby mieć kolejną ratunek dla swojej aplikacji.
źródło
Otwórz konsolę debugera, naciskając Cmd + Shift + R. Tam, wpisz
break malloc_error_break
aby ustawić punkt przerwania na początku
malloc_error_break
funkcji.Jeśli chcesz dowiedzieć się, jaki obiekt znajduje się pod adresem 0x1068310, możesz wpisać w konsoli debugera:
print-object 0x1068310
Oczywiście musisz to zrobić, gdy obiekt wciąż żyje - jeśli obiekt został już uwolniony do czasu, gdy to zrobisz, to nie zadziała.
źródło
po
aliasu lub jego odpowiednikaexpr -o
. W latach, które minęły od napisania tej odpowiedzi, silnik debugowania używany przez Xcode został zmieniony z GDB na LLDB, a LLDB ma inny zestaw poleceń.U mnie problem został rozwiązany przez
(gdb) call (void)_CFAutoreleasePoolPrintPools()
zaraz po wypadku. Adres na górze stosu był adresem sprawcy. Wrzuciłem a
retain
i voila.Adres podany w komunikacie dziennika nigdzie mnie nie zaprowadził. Nigdy nie pojawił się w żadnym z różnych instrumenetów. Najwyraźniej wskazówka do niektórych danych wewnętrznych, które zostały już uwolnione.
źródło
Dodanie symbolicznego punktu przerwania w Xcode 4
Tylko aktualizacja, aby było to istotne dla Xcode 4 ...
Z podręcznika użytkownika Xcode 4 :
źródło
Tak wygląda punkt przerwania malloc_error_break w oknie punkty przerwania w Xcode. Musisz zaznaczyć pola, aby działało.
tekst alternatywny http://www.martijnthe.nl/wp-content/uploads/2009/08/Afbeelding-1.png
źródło
Sprawdź swoje zajęcia i spójrz pod metodę dealloc. Upewnij się, że zadzwonisz
[super dealloc].
Miałem dokładnie ten sam problem i dowiedziałem się, że dzwonię
[self dealloc]
. Po prostu nie zwracam uwagi.źródło
Proszę znaleźć poniższe kroki, aby znaleźć obiekt, który jest wolny i zawiesić aplikację.
Możesz też odnieść się do poniższej prezentacji GIF.
źródło
Zwykle jest to spowodowane przez jakiegoś inspektora, na przykład safari lub podgląd safari. Zapoznaj się z postem lub postem i pytaniem .
Usunięcie zaznaczenia opcji AutoMatically Show Web .... spowoduje usunięcie tego problemu.
Uwaga, po prostu zamknij safari lub podgląd safari nie usunie tego problemu. Musisz też odznaczyć zarówno podgląd safari, jak i safari.
Jeśli to nie pomoże, zapoznaj się z tą odpowiedzią lub postem, aby go zdebugować.
źródło
W Xcode kliknij lewą stronę numeru linii, aby ustawić punkt przerwania. Następnie możesz go uruchomić, wykonując „Buduj i debuguj”.
Zaleca się, aby nie tworzyć obiektów,
autorelease
ponieważ pamięć jest towarem w telefonie iPhone. Apple zaleca bezpośrednie dzwonienierelease
.źródło
Aby znaleźć tego rodzaju problemy z pamięcią i wskaźnikami w ogóle, chcesz uruchomić kod w oparciu o moduł sprawdzania błędów pamięci w czasie wykonywania, taki jak Valgrind . To powinno być w stanie wskazać wiele rzeczy, które twój kod robi źle, poza tymi, które powodują awarię.
Valgrind może pracować na OSX (chociaż mówi, że jest „nieobsługiwany, niekompletny i zawiera błędy”), a po drobnym włamaniu ktoś zmusił go do pracy na plikach wykonywalnych iPhone SDK .
Jeszcze lepiej możesz wypróbować Instruments, który jest częścią XCode. Jest to poradnik do uruchamiania go tutaj .
źródło
Jeśli
malloc_error_break
nie pomaga ...Najlepszym sposobem rozwiązania tego błędu jest uruchomienie instrumentów przy
NSZombies
włączonych. Instruments oznaczy Cię flagą, gdy Zombie otrzyma wiadomość i możesz prześledzić bezpośrednio z powrotem do linii kodu.Wymagany Snow Leopard, co za ratownik!
źródło