_DEBUG vs NDEBUG


142

Kodun hata ayıklama bölümlerini belirtmek için hangi önişlemci tanımlaması kullanılmalıdır?

Kullanın #ifdef _DEBUGya #ifndef NDEBUGda ya da bunu yapmanın daha iyi bir yolu var #define MY_DEBUGmı , örneğin ?

Bence _DEBUGVisual Studio'ya özel, NDEBUG standardı mı?

Yanıtlar:


113

Visual Studio _DEBUG, /MTdveya /MDdseçeneğini belirttiğinizde tanımlar , NDEBUGstandart-C onaylarını devre dışı bırakır. Uygun olduğunda, yani bunları kullanın _DEBUGHata ayıklama kodu ile tutarlı olmak istiyorsanız , MS CRT hata ayıklama teknikleri ve NDEBUGsen tutarlı olmasını istiyorsanızassert() .

Kendi hata ayıklama makrolarınızı tanımlarsanız (ve derleyiciyi veya C çalışma zamanını hacklemezseniz), ayrılmış oldukları için adları alt çizgi ile başlatmaktan kaçının.


19
+1. Özellikle NDEBUG'un tek bir TU içinde # tanımsız ve # tanımlı olmasına izin verilir (ve <assert.h> ifadesinin yeniden girilmesi, onaylama makrosunu buna göre değiştirir). Bu beklenenden / istenenden farklı olduğundan, bu yanıtın dediği gibi "derleme çapında" bir hata ayıklama bayrağını denetlemek için başka bir makro kullanmak yaygındır.

1
Görünüşe göre, Visual Studio (IDE) değil, bu makroları tanımlayan derleyicinin kendisi. Bu cevap için çok teşekkürler!
Niklas R

NDEBUG, Windows Driver Kit 8.1'deki uygulama şablonları kullanıldığında tanımlanmamıştır. Bu durumda, _DEBUG'a güvenmeniz gerekebilir.
navossoc

53

NDEBUG standart mı?

Evet, C89, C99, C ++ 98, C ++ 2003, C ++ 2011, C ++ 2014 standartları için anlamsal "Hata Ayıklama" özelliğine sahip standart bir makrodur. _DEBUGStandartlarda makro yoktur .

C ++ 2003 standardı okuyucuyu "17.4.2.1 Üstbilgiler" de "sayfa 326" da standart C'ye gönderir.

Bu NDEBUG, Standard C kitaplığıyla aynıdır.

C89'da (C programcıları bu standardı standart C olarak adlandırdılar) "4.2 TANILAMA" bölümünde söylendi

http://port70.net/~nsz/c/c89/c89-draft.html

NDEBUG, kaynak dosyada bulunan noktada bir makro adı olarak tanımlanırsa, onaylama makrosu basitçe şu şekilde tanımlanır:

     #define assert(ignore) ((void)0)

_DEBUGVisual Studio https://msdn.microsoft.com/en-us/library/b0084kay.aspx içindeki makroların anlamına bakarsanız, bu makro otomatik olarak dil çalışma zamanı kitaplığı sürümünüz tarafından tanımlanır.


50

Güveniyorum NDEBUG, çünkü davranışları derleyiciler ve uygulamalar arasında standartlaştırılmış olan tek şey budur (standart iddia makrosu için belgelere bakın). Negatif mantık, küçük bir okunabilirlik hız darbesidir, ancak hızlı bir şekilde adapte olabileceğiniz yaygın bir deyimdir.

Böyle bir şeye _DEBUGgüvenmek, belirli bir derleyici ve kütüphane uygulamasının bir uygulama detayına güvenmek olacaktır. Diğer derleyiciler aynı kuralı seçebilir veya seçmeyebilir.

Üçüncü seçenek, projeniz için kendi makronuzu tanımlamaktır, ki bu oldukça mantıklıdır. Kendi makronuza sahip olmanız, uygulamalar arasında taşınabilirlik sağlar ve hata ayıklama kodunuzu iddialardan bağımsız olarak etkinleştirmenizi veya devre dışı bırakmanızı sağlar. Genel olarak, derleme zamanında etkinleştirilen farklı hata ayıklama bilgisi sınıflarına sahip olmamaya dikkat etmeliyim, çünkü muhtemelen küçük faydalar için inşa etmeniz (ve test etmeniz) gereken yapılandırma sayısında bir artışa neden olur.

Bu seçeneklerden herhangi birinde, projenizin bir parçası olarak üçüncü taraf kodu kullanırsanız, hangi sözleşmeyi kullandığını bilmeniz gerekir.


1
#if !defined(NDEBUG)<- @HostileFork demek istediğin bu değil mi? #ifdeğil #ifdefmi?
Bob Stein

1
@BobStein ile düzeltilen orijinal yorum: "Okunabilirliği hafifletmek için (hafifçe) yapmak için aldığım bir şey" speedbump ", hata ayıklama olmayan bir durumdan bahsederken #ifdef NDEBUG... ama sonra negatif mantığa özel dikkat çekmek #if !defined(NDEBUG). Aksi takdirde n yakalamak için biraz zor #ifndef NDEBUG"
HostileFork SE don don güven diyor

17

Makro, ifadelerin etkin NDEBUGolup olmadığını kontrol eder assert().

Benim görüşüme göre, bu diğer hata ayıklamalarından ayrıdır - bu yüzden NDEBUGprogramdaki hata ayıklama bilgilerini kontrol etmek dışında bir şey kullanıyorum . Kullandığım çerçeve, birlikte çalıştığım çerçeveye bağlı olarak değişir; farklı sistemlerin farklı etkinleştirici makroları vardır ve uygun olanı kullanırım.

Çerçeve yoksa, alt çizgi olmadan bir ad kullanırdım; bunlar 'uygulamaya' ayrılmaya eğilimlidirler ve isim çarpışmalarıyla ilgili sorunlardan kaçınmaya çalışırım - iki kez isim bir makro olduğunda.


Neden diğer hata ayıklama türlerinden farklı olduğunu düşündüğünüzü açıklayabilir misiniz? Hangi senaryolarda birini istiyorsunuz, diğerini değil?
Adrian McCarthy

4
Kodda diğer hata ayıklama veya izleme olanaklarını derlemesem bile ekleri aktif tutarım. İddialar imkansız durumları tanımlar. Genel izleme ve hata ayıklama, IMO'dan tamamen ayrıdır.
Jonathan Leffler

2
@AdrianMcCarthy: TÜM hata ayıklamayı etkinleştirdiyseniz, programların İNANILMAZ yavaş çalışmasına neden olabilir. Bu nedenle, hata ayıklama türlerini kategorilere ayırmak ve kişilerin bunları ayrı olarak etkinleştirmelerine / devre dışı bırakmalarına izin vermek yaygındır. MSVC'de standart kitaplık için std :: vector gibi çeşitli hata ayıklamayı etkinleştirmek / devre dışı bırakmak için kullandıkları iki veya üç tane vardır.
Mooing Duck

@MooingDuck: Kabul edildi, ancak 'hata ayıklama mevcut ve etkin' ve 'hata ayıklama mevcut ancak devre dışı' ve 'hata ayıklama mevcut değil' arasında ayrım yapın. Kullanılabilir / kullanılamaz kararı bir derleme zamanı sorunudur (C veya C ++ kodunda) ve etkinleştirilen / devre dışı bırakılan hata ayıklama kullanılabilir olduğunda bir çalışma zamanı kararıdır. 'En uygun hata ayıklama sistemleri' kullanılabilir araçlar etkin 'moduyla çalışır. (Yani, ham petrol etkili olabilir ve vahşi doğada çok sayıda ham - ama yeterince etkili - hata ayıklama sistemi var!)
Jonathan Leffler

2
@MooingDuck: Evet, bazı hata ayıklama kodları yavaş değişebilir. Bu durumda, belki yavaş kod önemsiz kontrollerinden bağımsız çalışır olmadığını kontrol etmek için bir yol istiyoruz. Ancak bu, bir kategoride iddiaları ve diğer kategoride #ifkontrol edilen kodu koymakla aynı şey değildir . assert(huge_object.IsValid());yavaş assert(ptr != nullptr);olmasa da yavaş olabilir . Jonathan'la oturum açmanın ve izlemenin muhtemelen en azından daha büyük projelerde iddialardan farklı olması gerektiğine katılıyorum , ancak günlüğe kaydetme veya izlemeyi hata ayıklama kodu olarak düşünmüyorum , bu yüzden açıklama istedim.
Adrian McCarthy

6

Tutarlı olun ve hangisinin önemli olduğu. Ayrıca, herhangi bir nedenle belirli bir DEBUG tanımlayıcısını kullanarak başka bir program veya araçla birlikte çalışmanız gerekiyorsa, bunu yapmak kolaydır

#ifdef THEIRDEBUG
#define MYDEBUG
#endif //and vice-versa

4

Ne yazık ki DEBUGaşırı yüklendi. Örneğin, RELEASE sürümleri için her zaman bir pdb dosyası oluşturmanız ve kaydetmeniz önerilir. Bu, -Zxbayraklardan biri ve -DEBUGbağlayıcı seçeneği anlamına gelir . Iken ve _DEBUGgibi çağrı zamanı kitaplığının özel hata ayıklama sürümleri ile ilgilidir . Ardından iddiaları devre dışı bırakır.mallocfreeNDEBUG

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.