Czy wyjątki „EXC_BREAKPOINT (SIGTRAP)” są spowodowane debugowaniem punktów przerwania?

84

Mam wielowątkową aplikację, która jest bardzo stabilna na wszystkich moich komputerach testowych i wydaje się stabilna dla prawie każdego z moich użytkowników (w oparciu o brak skarg na awarie). Jednak aplikacja często się zawiesza dla jednego użytkownika, który był na tyle uprzejmy, aby wysyłać raporty o awariach. Wszystkie raporty o awariach (~ 10 kolejnych raportów) wyglądają zasadniczo identycznie:

(... więcej tekstu poniżej)

Po pierwsze, spędziłem dużo czasu na badaniu [NSFont fontWithName: size:]. Pomyślałem, że być może czcionki użytkownika zostały w jakiś sposób spieprzone, więc [NSFont fontWithName: size:] żąda czegoś nieistniejącego i z tego powodu zawodzi. Dodałem trochę kodu za pomocą [[NSFontManager sharedFontManager] availableFontNamesWithTraits: NSItalicFontMask], aby sprawdzić z wyprzedzeniem dostępność czcionek. Niestety, te zmiany nie rozwiązały problemu.

Zauważyłem, że zapomniałem usunąć niektóre punkty przerwania debugowania, w tym _NSLockError, [NSException raise] i objc_exception_throw. Jednak aplikacja została zdecydowanie zbudowana przy użyciu „Release” jako aktywnej konfiguracji kompilacji. Zakładam, że użycie konfiguracji „Release” uniemożliwia ustawienie jakichkolwiek punktów przerwania - ale z drugiej strony nie jestem pewien, jak dokładnie działają punkty przerwania ani czy program musi być uruchamiany z poziomu gdb, aby punkty przerwania miały jakikolwiek efekt.

Moje pytania to: czy pozostawienie ustawionych punktów przerwania może być przyczyną awarii zaobserwowanych przez użytkownika? Jeśli tak, dlaczego punkty przerwania miałyby powodować problem tylko dla tego jednego użytkownika? Jeśli nie, czy ktokolwiek inny miał podobne problemy z [NSFont fontWithName: size:]?

Prawdopodobnie spróbuję po prostu usunąć punkty przerwania i odesłać do użytkownika, ale nie jestem pewien, ile waluty pozostało temu użytkownikowi. Chciałbym też bardziej ogólnie zrozumieć, czy pozostawienie ustawionych punktów przerwania może spowodować problem (gdy aplikacja jest budowana przy użyciu konfiguracji „Release”).

Dennis
źródło

Odpowiedzi:

189

Czy wyjątki „EXC_BREAKPOINT (SIGTRAP)” są spowodowane debugowaniem punktów przerwania?

Nie. Z drugiej strony, właściwie: SIGTRAP (pułapka śladowa) spowoduje, że debugger przerwie (przerwie) twój program, tak samo jak rzeczywisty punkt przerwania. Ale to dlatego, że debugger zawsze się psuje po awarii, a SIGTRAP (podobnie jak kilka innych sygnałów ) jest jednym z rodzajów awarii.

SIGTRAP są generalnie powodowane przez rzucanie NSExceptions, ale nie zawsze - możliwe jest nawet samodzielne podniesienie jednego.

Zauważyłem, że zapomniałem usunąć niektóre punkty przerwania debugowania, w tym _NSLockError, [NSException raise] i objc_exception_throw.

To nie są punkty przerwania. Dwie z nich to funkcje i -[NSException raise]metoda.

Czy chodziło Ci o ustawienie punktów przerwania dla tych funkcji i tej metody?

Zakładam, że użycie konfiguracji „Release” zapobiega ustawianiu jakichkolwiek punktów przerwania -

Nie.

Konfiguracje są konfiguracjami kompilacji . Wpływają na sposób, w jaki Xcode buduje aplikacje.

Punkty przerwania nie są częścią kompilacji; ustawiasz je w debugerze. Istnieją tylko, są trafione i zatrzymują program tylko wtedy, gdy uruchamiasz go w debugerze.

Ponieważ nie są one częścią kompilacji, nie można przekazać punktów przerwania użytkownikowi, po prostu przekazując mu pakiet aplikacji.

Nie jestem pewien, jak dokładnie działają punkty przerwania…

Kiedy twój program osiągnie punkt przerwania, debugger przerywa (przerywa) twój program, po czym możesz sprawdzić stan programu i ostrożnie przejść do przodu, aby zobaczyć, jak program się nie powiedzie.

Ponieważ jest to debugger, który zatrzymuje twój program, punkty przerwania nie mają wpływu, gdy nie uruchamiasz programu w debugerze.

… Lub czy program musi być uruchamiany z poziomu gdb, aby punkty przerwania miały jakikolwiek efekt.

To robi. Punkty przerwania debugera działają tylko w debugerze.

Moje pytania to: czy pozostawienie ustawionych punktów przerwania może być przyczyną awarii zaobserwowanych przez użytkownika?

Nie.

Po pierwsze, jak zauważono, nawet jeśli te punkty przerwania zostały w jakiś sposób przeniesione do systemu użytkownika, punkty przerwania są skuteczne tylko w debugerze. Debuger nie może zatrzymać się w punkcie przerwania, jeśli program nie działa w debugerze. Użytkownik prawie na pewno nie uruchamia Twojej aplikacji w debugerze, zwłaszcza że wylogował się z niej awaryjnie.

Nawet gdyby tak było uruchomić aplikację pod debugger z tych wszystkich wymienionych punktów przerwań, punkt przerwania jest trafiony tylko gdy program osiągnie ten punkt, więc jeden z tych przerwań mógł tylko ogień, jeśli lub kakao nazywa _NSLockError, -[NSException raise]albo objc_exception_throw. Dotarcie do tego punktu nie byłoby przyczyną problemu, byłby objawem problemu.

A jeśli nastąpiła awaria w wyniku wywołania jednego z nich, w dzienniku awarii przynajmniej jeden z nich zostałby nazwany. Tak nie jest.

Nie było to więc związane z punktami przerwania (inna maszyna, debugger nie jest zaangażowany) i nie był to wyjątek Cocoa - jak wspomniałem, wyjątki Cocoa są jedną z przyczyn SIGTRAPów, ale nie są jedyne. Napotkałeś inny.

Jeśli nie, czy ktokolwiek inny miał podobne problemy z [NSFont fontWithName: size:]?

W żaden sposób nie możemy stwierdzić, czy jakiekolwiek problemy, które mieliśmy, są podobne, ponieważ wyłączyłeś dziennik awarii. Nie wiemy nic o tym, w jakim kontekście doszło do katastrofy.

Jedyną rzeczą, którą dobrze jest wyciąć, jest sekcja „Obrazy binarne”, ponieważ nie mamy twoich pakietów dSYM, co oznacza, że ​​nie możemy użyć tej sekcji do symbolizacji dziennika awarii.

Ty, z drugiej strony, możesz. W tym celu napisałem aplikację ; prześlij do niego dziennik awarii, który powinien automatycznie wykryć pakiet dSYM (zachowujesz pakiet dSYM dla każdej dystrybuowanej kompilacji wydania, prawda?) i przywrócić nazwy funkcji i metod do śladu stosu, gdziekolwiek pojawiają się twoje funkcje i metody.

Aby uzyskać więcej informacji, zobacz przewodnik debugowania Xcode .

Peter Hosey
źródło
3
Wow, dzięki za wyczerpującą odpowiedź. • „Czy chodziło Ci o ustawienie punktów przerwania dla tych funkcji…” Tak, o to mi chodziło. • „Punkty przerwania nie są częścią kompilacji… One tylko istnieją, są trafiane i zatrzymują program tylko wtedy, gdy uruchamiasz program w debugerze” Dzięki, właśnie to chciałem wiedzieć. • „symbolizuj dziennik awarii… Napisałem w tym celu aplikację” Ładna aplikacja. Generalnie „symbolizuję” przez samą intuicję - ale twoja aplikacja jest lepszym sposobem! • Doszedłem do wniosku, że musi to mieć jakiś problem z czcionką użytkownika i z tej perspektywy będzie nad tym działać.
Dennis
7

Jest bardzo prawdopodobne, że ten użytkownik ma zainstalowaną uszkodzoną czcionkę. Ślad stosu zdecydowanie potwierdza tę hipotezę, podobnie jak fakt, że wpływa tylko na jednego użytkownika.

W takim przypadku niewiele można zrobić, poza nakłonieniem użytkownika do usunięcia naruszającej czcionki, ponieważ awarie, które występują, mają miejsce głęboko w kodzie Apple.

Spróbuj zachęcić użytkownika do uruchomienia sprawdzania poprawności czcionki w Albumie z czcionkami. Aby to zrobić, uruchom Album z czcionkami, kliknij opcję Wszystkie czcionki na liście źródeł, a następnie wybierz wszystkie wymienione czcionki. Następnie możesz wybrać opcję Sprawdź poprawność czcionek z menu Plik .

Rob Keniger
źródło
1
Dziękuję za tę wskazówkę dotyczącą Albumu z czcionkami - wiem bardzo mało o czcionkach i faktycznie miałem ciekawy czas na walidację własnych czcionek ... Zasugeruję, aby użytkownik spróbował tego.
Dennis
0

Punkty przerwania nie są zapisywane w pliku binarnym. Istnieje duże prawdopodobieństwo, że ta osoba ma zepsutą instalację systemu operacyjnego. Sprawdź dzienniki konsoli pod kątem komunikatów dyld.

Azeem.Butt
źródło
Dzięki za tę szybką odpowiedź! Przeglądając ten problem w Google zauważyłem, że inni mają EXC_BREAKPOINTS powiązane z wiadomościami dyld - ale moje dzienniki awarii nie pokazują żadnych wiadomości z dyld.
Dennis
0

Miałem ten sam błąd. Z niewyjaśnionych powodów punkt przerwania był odpowiedzialny za zgłoszenie wyjątku EXC_BREAKPOINT . Rozwiązaniem było usunięcie punktu przerwania, a kod działa.

EXC_BREAKPOINT jest rodzajem wyjątku używanego przez debugery. Po ustawieniu punktu przerwania w kodzie kompilator wstawia wyjątek tego typu w kodzie wykonywalnym. Gdy wykonanie osiągnie ten punkt, wyjątek jest zgłaszany i debuger przechwytuje go. Następnie debugger wyświetla kod w wierszu „punkt przerwania”. Tak działają debuggery. Ale w tym przypadku debugger nie obsługuje poprawnie wyjątku i jest przedstawiany jako zwykły błąd wyjątku.

Znalazłem ten błąd dwa razy w życiu:

  • jeden używający Xcode około rok temu.
  • drugi używa Visual C ++ około 15 lat temu.
veladan
źródło
Dziwne, że otrzymałem ten błąd bez żadnych punktów przerwania.
kelin
Nie mówię, że ten błąd występuje tylko w punktach przerwania: EXC_BREAKPOINT może się zdarzyć z wielu powodów. To, co wyjaśniam, to para bardzo rzadkich przypadków, w których punkt przerwania generuje nieobsługiwany wyjątek.
veladan