Zakładając, że C ++ wspiera je kompilatora, czy jest jakiś szczególny powód nie do użytku __FILE__
, __LINE__
a __FUNCTION__
do rejestrowania i celów debugowania?
Przede wszystkim interesuje mnie podawanie użytkownikowi wprowadzających w błąd danych - na przykład zgłaszanie nieprawidłowego numeru linii lub funkcji w wyniku optymalizacji - lub przyjmowanie w rezultacie spadku wydajności.
Zasadniczo mogę zaufać __FILE__
, __LINE__
i __FUNCTION__
aby zawsze zrobić dobry uczynek?
c++
debugging
logging
c-preprocessor
Runcible
źródło
źródło
Odpowiedzi:
__FUNCTION__
jest niestandardowy,__func__
istnieje w C99 / C ++ 11. Pozostałe (__LINE__
i__FILE__
) są po prostu w porządku.Zawsze zgłasza właściwy plik i wiersz (oraz funkcję, jeśli zdecydujesz się użyć
__FUNCTION__
/__func__
). Optymalizacja nie jest czynnikiem, ponieważ jest rozwijaniem makr w czasie kompilacji; będzie nie wpływa w żaden sposób wydajność.źródło
__func__
jest rodzajem problemu w C ++. C99 nie mówi ani słowa o domyślnych argumentach i tak dalej, w przypadkach, w których nie jest tak oczywiste, jak__func__
powinno się zachować w C ++.__func__
istnieje w C99, a nie w C ++. Niezależnie od tego, myślę, że rozsądna implementacja__func__
w c ++ spowodowałaby po prostu zniekształconą nazwę. Ponieważ nie jestem autorem kompilatorów, nie jest to moja sprawa.__FUNCTION__
w ogóle nie obsługują ? Które kompilatory oprócz niedawnego gcc traktują to jako zmienną, a nie makro?__func__
jest teraz w standardzie C ++ 11.W rzadkich przypadkach może być przydatna zmiana podanej linii
__LINE__
na inną. Widziałem, że GNU configure robi to w niektórych testach, aby zgłosić odpowiednie numery wierszy po wstawieniu jakiegoś voodoo między wierszami, które nie pojawiają się w oryginalnych plikach źródłowych. Na przykład:Następujące linie będą zaczynać się od
__LINE__
100. Opcjonalnie możesz dodać nową nazwę plikuRzadko się przydaje. Ale jeśli jest to potrzebne, nie znam żadnych alternatyw. W rzeczywistości zamiast wiersza można również użyć makra, które musi skutkować jedną z dwóch powyższych form. Korzystając z biblioteki preprocesora boost, możesz zwiększyć bieżący wiersz o 50:
Pomyślałem, że warto o tym wspomnieć, ponieważ zapytałeś o użycie
__LINE__
i__FILE__
. C ++ nigdy nie daje wystarczająco dużo niespodzianek :)Edycja: @Jonathan Leffler podaje kilka innych dobrych przypadków użycia w komentarzach:
źródło
FYI: g ++ oferuje niestandardowe makro __PRETTY_FUNCTION__. Do tej pory nie wiedziałem o C99 __func__ (dzięki Evan!). Myślę, że nadal wolę __PRETTY_FUNCTION__, gdy jest on dostępny dla dodatkowego zakresu klas.
PS:
źródło
Osobiście niechętnie używam ich do niczego poza debugowaniem wiadomości. Zrobiłem to, ale staram się nie pokazywać tego rodzaju informacji klientom lub użytkownikom końcowym. Moi klienci nie są inżynierami i czasami nie znają się na komputerach. Mógłbym zarejestrować te informacje w konsoli, ale, jak powiedziałem, niechętnie, z wyjątkiem kompilacji debugowania lub narzędzi wewnętrznych. Przypuszczam jednak, że zależy to od bazy klientów, którą masz.
źródło
C ++ 20
std::source_location
C ++ w końcu dodał opcję niebędącą makrami i prawdopodobnie będzie dominować w pewnym momencie w przyszłości, gdy C ++ 20 stanie się powszechny:
Dokumentacja mówi:
gdzie NTBS oznacza „ciąg bajtów zakończony wartością zerową”.
Spróbuję, gdy wsparcie dotrze do GCC, GCC 9.1.0
g++-9 -std=c++2a
nadal go nie obsługuje.Oświadczenia https://en.cppreference.com/w/cpp/utility/source_location będą wyglądać następująco:
Możliwe wyjście:
__PRETTY_FUNCTION__
vs__FUNCTION__
vs__func__
vsstd::source_location::function_name
Odpowiedzieli na: Jaka jest różnica między __PRETTY_FUNCTION__, __FUNCTION__, __func__?
źródło
<experimental/source_location>
aktualnym gcc-9.Używam ich cały czas. Jedyne, o co się martwię, to podawanie adresu IP w plikach dziennika. Jeśli nazwy Twoich funkcji są naprawdę dobre, możesz ułatwić odkrycie tajemnicy handlowej. To trochę jak wysyłanie z symbolami debugowania, tylko trudniej jest znaleźć rzeczy. W 99,999% przypadków nic złego z tego nie wyniknie.
źródło
strings
narzędzia do wyodrębnienia wszystkich danych podobnych do ciągu z pliku wykonywalnego jest trywialne . Można wyodrębnić nawet skompresowane pliki wykonywalne. Uważaj na to, co wysyłasz do witryny klienta. Często zdarza się, że konkurenci są w stanie zdobyć Twoje pliki wykonywalne, nawet jeśli nie powinni tego robić.