2009-09-07 5 views
15

Wiele razy pracuję ze zoptymalizowanym kodem (czasami nawet z wektoryzowanymi pętlami), które zawierają błędy i tym podobne. Jak debugować taki kod? Szukam wszelkiego rodzaju narzędzi lub technik. Korzystam z następujących (prawdopodobnie nieaktualnych) narzędzi, dlatego zamierzam dokonać aktualizacji.Jakie są skuteczne sposoby debugowania zoptymalizowanego programu C/C++?

używam następujące:

  • Ponieważ z DDD, nie można zobaczyć kod, używam gdb + dissambler komendy i zobaczyć wytwarzanego kodu; Nie mogę naprawdę przejść przez program, korzystając z tego.
  • ndisasm

Dzięki

+0

To nie jest niesamowicie wnikliwe, ale MSDN ma artykuł o debugowaniu zoptymalizowanego kodu (przynajmniej w świecie Windows): http://msdn.microsoft.com/en-us/library/606cbtzs.aspx. – reuben

+0

Nie wiem, czy nasz kod jest multiplattform, ale przy użyciu Visual Studio można debugować program zoptymalizowany pod kątem kompilatora, jak również wersję debugowania. Przejdź przez kod, punkty przywracania, zegarek itp. –

+0

Działa na systemie UNIX OS tylko – vehomzzz

Odpowiedz

19

To jest zawsze trudniejsze do debugowania zoptymalizowanych programów, ale nie zawsze są sposoby. Kilka dodatkowych wskazówek:

  • Wykonaj kompilację debugowania i zobacz, czy otrzymasz ten sam błąd w kompilacji debugowania. Nie ma potrzeby debugowania zoptymalizowanej wersji, jeśli nie musisz.
  • Użyj valgrind, jeśli na platformie, która go obsługuje. Błędy, które widzisz, mogą być trudniejsze do zrozumienia, ale wczesne wykrycie problemu upraszcza debugowanie.
  • debugowanie printf jest prymitywne, ale czasami jest to najprostszy sposób, jeśli masz złożony problem, który pojawia się tylko w zoptymalizowanych kompilacjach.
  • Jeśli podejrzewasz problem z synchronizacją (szczególnie w programie wielowątkowym), rzuć własną wersją asercji, która przerwie lub wydrukuje, jeśli warunek zostanie naruszony, i użyje go w kilku wybranych miejscach, aby wykluczyć możliwe problemy.
  • Sprawdź, czy możesz odtworzyć problem bez użycia -fomit-frame-pointers, ponieważ powoduje to, że kod jest bardzo trudny do debugowania oraz z włączonym -O2 lub -O3. To może dostarczyć wystarczających informacji, aby znaleźć przyczynę problemu.
  • Wyodrębnij części kodu, zbuduj pakiet testowy i sprawdź, czy można zidentyfikować przypadki testowe, które zawiodły. Dużo łatwiej jest debugować jedną funkcję niż cały program.
  • Spróbuj wyłączyć optymalizację jeden po drugim za pomocą opcji -fno-X. Może to pomóc w znalezieniu typowych problemów, takich jak ścisłe problemy z aliasingiem.
  • Włącz więcej ostrzeżeń kompilatora. Niektóre rzeczy, takie jak ścisłe problemy z aliasingiem, mogą generować ostrzeżenia kompilatora, jeśli powodują różnice w zachowaniu między różnymi poziomami optymalizacji.
+2

Błąd z debugowaniem printf może maskować błędy optymalizacji, ponieważ kod przekazujący dane do wywołania printf może uniemożliwić wykonanie kodu ta sama optymalizacja. (Miałem wiele przypadków, w których kod debugowania działa i zoptymalizowano, nie są to błędy optymalizatora.) OTOH, printf pomoże ci znaleźć błędy optymalizatora i jest wskazówką, że musisz zanurkować w zespole, aby ustalić, czy masz błąd optymalizatora: – jmucchiello

+0

+1 za sugerowanie kompilacji debugowania i valgrinda - zakładając, że nie natknąłeś się na błąd kompilatora, jedyny powód, dla którego zoptymalizowana kompilacja zakończy się niepowodzeniem, gdy kompilacja debugowania nie będzie polegała na tym, że ty tupiesz inna (i ważniejsza) część pamięci – kdgregory

1

Zawsze jest łatwiej debugować wersję niezoptymalizowaną, oczywiście. W przeciwnym razie pomocny może być demontaż kodu. Inne techniki, których używałem, to częściowa de-optymalizacja kodu poprzez wymuszenie wydrukowania lub zalogowania wyników pośrednich lub zmiana zmiennej krytycznej na "zmienną", dzięki czemu mogę przynajmniej przyjrzeć się wartościw debugerze.

6

Podczas debugowania kompilacji wydania można wstawić nacieki __asm; jako symbol zastępczy dla punktów przerwania (int 3). Jest to miłe, ponieważ można zagwarantować lokalizacje punktów przerwania bez komplikowania optymalizacji kompilatora lub pisania instrukcji printf/cout.

+1

Nie wiem o GCC, ale posiadanie wbudowanego bloku złożenia w MSVC może mieć wpływ na optymalizację: "na niektóre inne optymalizacje obejmujące całą funkcję wpłynie włączenie języka asemblera w funkcja "- http://msdn.microsoft.com/en-us/library/5hd5ywk0.aspx –

0

Jest szansa, że ​​ten kod nazywa się zoptymalizowanym kodowaniem, aby golić cykle (co utrudnia debugowanie), ale nie jest zbyt zoptymalizowany.Here is an example of what I mean.

Wyłączałbym optymalizację kompilatora, debugowałam i stroję go samemu, a następnie włączam optymalizację kompilatora, jeśli kod ma aktywne punkty, które faktycznie znajdują się w kodzie, który widzi kompilator (nie w zewnętrznych bibliotekach). (Definiuję hotspot jako część kodu, w którym często znajduje się komputer.) Automatycznie zwalnia pętle zawierające wywołania funkcji, ponieważ kradną komputer.)