Jawaban:
Visual Studio mendefinisikan _DEBUG
ketika Anda menentukan opsi /MTd
atau /MDd
, NDEBUG
menonaktifkan pernyataan standar-C. Gunakan jika perlu, yaitu _DEBUG
jika Anda ingin kode debug Anda konsisten dengan teknik debugging MS CRT dan NDEBUG
jika Anda ingin konsisten dengannya assert()
.
Jika Anda mendefinisikan makro debug Anda sendiri (dan Anda tidak meretas kompiler atau runtime C), hindari mulai nama dengan garis bawah, karena ini dicadangkan.
Apakah standar NDEBUG?
Ya itu adalah makro standar dengan semantic "Not Debug" untuk C89, C99, C ++ 98, C ++ 2003, C ++ 2011, C ++ 2014 standar. Tidak ada _DEBUG
makro dalam standar.
Standar C ++ 2003 mengirim pembaca di "halaman 326" di "17.4.2.1 Header" ke standar C.
NDEBUG itu serupa dengan Ini sama dengan pustaka C Standar.
Dalam C89 (programmer C menyebut standar ini sebagai standar C) di bagian "4.2 DIAGNOSTIK" dikatakan
http://port70.net/~nsz/c/c89/c89-draft.html
Jika NDEBUG didefinisikan sebagai nama makro pada titik di file sumber di mana disertakan, makro pernyataan didefinisikan hanya sebagai
#define assert(ignore) ((void)0)
Jika melihat arti _DEBUG
makro di Visual Studio
https://msdn.microsoft.com/en-us/library/b0084kay.aspx
maka akan terlihat, bahwa makro ini secara otomatis ditentukan oleh сhoice versi perpustakaan runtime bahasa Anda.
Saya mengandalkan NDEBUG
, karena itu adalah satu-satunya yang perilakunya distandardisasi di seluruh kompiler dan implementasi (lihat dokumentasi untuk makro pernyataan standar). Logika negatif adalah speedbump keterbacaan kecil, tapi itu adalah idiom umum yang dapat Anda adaptasi dengan cepat.
Untuk bergantung pada sesuatu seperti _DEBUG
akan bergantung pada detail implementasi dari kompiler dan implementasi perpustakaan tertentu. Kompiler lain mungkin atau mungkin tidak memilih konvensi yang sama.
Opsi ketiga adalah mendefinisikan makro Anda sendiri untuk proyek Anda, yang cukup masuk akal. Memiliki makro Anda sendiri memberi Anda portabilitas di seluruh implementasi dan memungkinkan Anda untuk mengaktifkan atau menonaktifkan kode debug Anda secara independen dari pernyataan. Meskipun, secara umum, saya menyarankan agar tidak memiliki kelas informasi debug yang berbeda yang diaktifkan pada waktu kompilasi, karena hal itu menyebabkan peningkatan jumlah konfigurasi yang harus Anda bangun (dan uji) untuk manfaat yang bisa dibilang kecil.
Dengan salah satu opsi ini, jika Anda menggunakan kode pihak ketiga sebagai bagian dari proyek Anda, Anda harus mengetahui konvensi mana yang digunakannya.
#if !defined(NDEBUG)
<- @HostileFork bukankah itu yang Anda maksud? #if
bukan #ifdef
?
#ifdef NDEBUG
... tapi kemudian minta perhatian khusus pada logika negatif dengan #if !defined(NDEBUG)
. Kalau tidak, agak sulit untuk menangkap #ifndef NDEBUG
"
Makro NDEBUG
mengontrol apakah assert()
pernyataan aktif atau tidak.
Dalam pandangan saya, itu terpisah dari debugging lain - jadi saya menggunakan sesuatu selain NDEBUG
untuk mengontrol informasi debug dalam program. Apa yang saya gunakan bervariasi, tergantung pada kerangka kerja saya; sistem yang berbeda memiliki makro yang memungkinkan yang berbeda, dan saya menggunakan apa pun yang sesuai.
Jika tidak ada kerangka kerja, saya akan menggunakan nama tanpa garis bawah utama; mereka cenderung dicadangkan untuk 'implementasi' dan saya mencoba untuk menghindari masalah dengan tabrakan nama - jadi ketika nama adalah makro.
#if
-kontrol kode di yang lain. assert(huge_object.IsValid());
mungkin lambat sementara assert(ptr != nullptr);
mungkin tidak. Saya setuju dengan Jonathan bahwa logging dan tracing mungkin harus berbeda dari pernyataan, setidaknya dalam proyek yang lebih besar, tetapi saya tidak menganggap logging atau tracing sebagai kode debug, itulah sebabnya saya meminta klarifikasi.
Sayangnya DEBUG
kelebihan beban. Misalnya, disarankan untuk selalu menghasilkan dan menyimpan file pdb untuk RELEASE build. Yang berarti salah satu opsi -Zx
flag, dan -DEBUG
linker. Sementara _DEBUG
berkaitan dengan versi debug khusus perpustakaan runtime seperti panggilan ke malloc
dan free
. Maka NDEBUG
akan menonaktifkan asersi.