Odpowiedzi:
Program Visual Studio definiuje, _DEBUGgdy określisz opcję /MTdlub /MDd, NDEBUGwyłącza asercje w standardzie C. Używaj ich w odpowiednich przypadkach, np. _DEBUGJeśli chcesz, aby Twój kod debugowania był spójny z technikami debugowania MS CRT i NDEBUGjeśli chcesz być spójny z assert().
Jeśli zdefiniujesz własne makra debugowania (i nie włamujesz się do kompilatora ani środowiska wykonawczego C), unikaj rozpoczynania nazw od podkreślenia, ponieważ są one zarezerwowane.
Czy NDEBUG jest standardem?
Tak, jest to standardowe makro z semantycznym „Not Debug” dla standardów C89, C99, C ++ 98, C ++ 2003, C ++ 2011, C ++ 2014. W _DEBUGstandardach nie ma makr.
Standard C ++ 2003 wysyła czytelnika na „stronę 326” w „17.4.2.1 Nagłówki” do standardu C.
Ten NDEBUG jest podobny do tego, co jest tym samym, co standardowa biblioteka C.
W C89 (programiści C nazywali ten standard standardem C) w sekcji "4.2 DIAGNOSTYKA" powiedziano
http://port70.net/~nsz/c/c89/c89-draft.html
Jeśli NDEBUG jest zdefiniowany jako nazwa makra w punkcie w pliku źródłowym, w którym jest uwzględniony, makro assert jest definiowane po prostu jako
#define assert(ignore) ((void)0)
Jeśli spojrzysz na znaczenie _DEBUGmakr w Visual Studio
https://msdn.microsoft.com/en-us/library/b0084kay.aspx
, zobaczysz, że to makro jest automatycznie definiowane przez wybór wersji biblioteki środowiska uruchomieniowego języka.
Polegam na tym NDEBUG, ponieważ jest to jedyny, którego zachowanie jest znormalizowane między kompilatorami i implementacjami (zobacz dokumentację standardowego makra assert). Logika negatywna to niewielki wzrost czytelności, ale jest to powszechny idiom, do którego można szybko się dostosować.
Poleganie na czymś podobnym _DEBUGbyłoby poleganiem na szczegółach implementacji konkretnego kompilatora i implementacji biblioteki. Inni kompilatorzy mogą, ale nie muszą, wybrać tę samą konwencję.
Trzecią opcją jest zdefiniowanie własnego makra dla projektu, co jest całkiem rozsądne. Posiadanie własnego makra zapewnia przenośność między implementacjami i umożliwia włączanie lub wyłączanie kodu debugowania niezależnie od stwierdzeń. Chociaż, ogólnie rzecz biorąc, odradzam posiadanie różnych klas informacji debugowania, które są włączane w czasie kompilacji, ponieważ powoduje to wzrost liczby konfiguracji, które musisz zbudować (i przetestować) z prawdopodobnie niewielkimi korzyściami.
W przypadku dowolnej z tych opcji, jeśli używasz kodu innej firmy w ramach swojego projektu, musisz wiedzieć, jakiej konwencji używa.
#if !defined(NDEBUG)<- @HostileFork czy nie to miałeś na myśli? #ifnie #ifdef?
#ifdef NDEBUG... ale zwróć szczególną uwagę na logikę negatywną #if !defined(NDEBUG). W przeciwnym razie trochę trudno jest złapać n #ifndef NDEBUG”
Makro NDEBUGkontroluje, czy assert()instrukcje są aktywne, czy nie.
Moim zdaniem jest to niezależne od jakiegokolwiek innego debugowania - więc używam czegoś innego niż NDEBUGkontrolowanie informacji debugowania w programie. To, czego używam, różni się w zależności od frameworka, z którym pracuję; różne systemy mają różne makra włączające i używam tego, co jest odpowiednie.
Jeśli nie ma frameworka, użyłbym nazwy bez początkowego podkreślenia; są one zwykle zarezerwowane dla „implementacji” i staram się unikać problemów z kolizjami nazw - podwójnie, gdy nazwa jest makrem.
#ifkontrolowanego kodu w drugiej. assert(huge_object.IsValid());może być powolny, podczas gdy assert(ptr != nullptr);prawdopodobnie nie. Zgadzam się z Jonathanem, że logowanie i śledzenie powinny prawdopodobnie różnić się od asercji, przynajmniej w większych projektach, ale nie myślę o logowaniu lub śledzeniu jako o kodzie debugowania, dlatego poprosiłem o wyjaśnienie.
Niestety DEBUGjest mocno przeciążony. Na przykład, zaleca się, aby zawsze generować i zapisywać plik pdb dla wersji RELEASE. Co oznacza jedną z -Zxflag i -DEBUGopcję konsolidatora. Podczas gdy _DEBUGodnosi się do specjalnych wersji debugowania biblioteki wykonawczej, takich jak wywołania malloci free. Następnie NDEBUGwyłączy asercje.