Câu trả lời:
Visual Studio xác định _DEBUG
khi bạn chỉ định /MTd
hoặc /MDd
tùy chọn, NDEBUG
vô hiệu hóa các xác nhận C-tiêu chuẩn. Sử dụng chúng khi thích hợp, tức là _DEBUG
nếu bạn muốn mã gỡ lỗi của mình phù hợp với các kỹ thuật gỡ lỗi MS CRT và NDEBUG
nếu bạn muốn phù hợp với assert()
.
Nếu bạn xác định các macro gỡ lỗi của riêng mình (và bạn không hack trình biên dịch hoặc thời gian chạy C), hãy tránh bắt đầu các tên có dấu gạch dưới, vì chúng được bảo lưu.
Là tiêu chuẩn NDEBUG?
Vâng, đó là một macro tiêu chuẩn với ngữ nghĩa "Không gỡ lỗi" cho các tiêu chuẩn C89, C99, C ++ 98, C ++ 2003, C ++ 2011, C ++ 2014. Không có_DEBUG
macro trong các tiêu chuẩn.
Tiêu chuẩn C ++ 2003 gửi người đọc tại "trang 326" tại "17.4.2.1 Tiêu đề" tới tiêu chuẩn C.
Đó là NDEBUG tương tự như Điều này giống như thư viện C chuẩn.
Trong C89 (lập trình viên C gọi tiêu chuẩn này là tiêu chuẩn C) trong phần "4.2 CHẨN ĐOÁN", người ta đã nói
http://port70.net/~nsz/c/c89/c89-draft.html
Nếu NDEBUG được định nghĩa là tên macro tại điểm trong tệp nguồn được bao gồm, macro xác nhận được định nghĩa đơn giản là
#define assert(ignore) ((void)0)
Nếu nhìn vào ý nghĩa của các _DEBUG
macro trong Visual Studio
https://msdn.microsoft.com/en-us/l
Library / b0084kay.aspx thì sẽ thấy rằng macro này được tự động xác định bởi phiên bản thư viện thời gian chạy ngôn ngữ của bạn.
Tôi dựa vào NDEBUG
, bởi vì đó là người duy nhất có hành vi được chuẩn hóa trên các trình biên dịch và triển khai (xem tài liệu về macro xác nhận tiêu chuẩn). Logic tiêu cực là một tốc độ dễ đọc nhỏ, nhưng đó là một thành ngữ phổ biến mà bạn có thể nhanh chóng thích nghi.
Dựa vào một cái gì đó giống như _DEBUG
sẽ dựa vào một chi tiết triển khai của một trình biên dịch và triển khai thư viện cụ thể. Trình biên dịch khác có thể hoặc không thể chọn cùng một quy ước.
Tùy chọn thứ ba là xác định macro của riêng bạn cho dự án của bạn, điều này khá hợp lý. Có macro của riêng bạn cung cấp cho bạn tính di động trong các triển khai và nó cho phép bạn bật hoặc tắt mã gỡ lỗi của mình một cách độc lập với các xác nhận. Mặc dù, nói chung, tôi khuyên bạn không nên có các loại thông tin gỡ lỗi khác nhau được bật tại thời điểm biên dịch, vì nó gây ra sự gia tăng số lượng cấu hình bạn phải xây dựng (và kiểm tra) vì lợi ích nhỏ có thể tranh cãi.
Với bất kỳ tùy chọn nào trong số các tùy chọn này, nếu bạn sử dụng mã của bên thứ ba như một phần của dự án của mình, bạn sẽ phải biết về quy ước mà nó sử dụng.
#if !defined(NDEBUG)
<- @hostileFork không phải là ý bạn sao? #if
không #ifdef
?
#ifdef NDEBUG
... nhưng sau đó đặc biệt chú ý đến logic tiêu cực #if !defined(NDEBUG)
. Nếu không thì hơi khó để bắt được n #ifndef NDEBUG
"
Các macro NDEBUG
kiểm soát xem các assert()
câu lệnh có hoạt động hay không.
Theo quan điểm của tôi, nó tách biệt với mọi gỡ lỗi khác - vì vậy tôi sử dụng một cái gì đó ngoài NDEBUG
việc kiểm soát thông tin gỡ lỗi trong chương trình. Những gì tôi sử dụng khác nhau, tùy thuộc vào khung tôi đang làm việc; các hệ thống khác nhau có các macro cho phép khác nhau và tôi sử dụng bất cứ thứ gì phù hợp.
Nếu không có khung, tôi sẽ sử dụng tên mà không có dấu gạch dưới hàng đầu; những điều này có xu hướng được dành riêng cho 'việc thực hiện' và tôi cố gắng tránh các vấn đề với xung đột tên - gấp đôi khi tên đó là một macro.
#if
mã được kiểm soát trong một danh mục khác. assert(huge_object.IsValid());
có thể chậm trong khi assert(ptr != nullptr);
có lẽ không. Tôi đồng ý với Jonathan rằng việc ghi nhật ký và theo dõi có lẽ phải khác biệt với các xác nhận, ít nhất là trong các dự án lớn hơn, nhưng tôi không nghĩ đến việc ghi nhật ký hoặc theo dõi là mã gỡ lỗi, đó là lý do tại sao tôi yêu cầu làm rõ.
Thật không may DEBUG
là quá tải nặng. Chẳng hạn, nên luôn luôn tạo và lưu tệp pdb cho các bản dựng ĐÁNG TIN CẬY. Có nghĩa là một trong những -Zx
cờ và -DEBUG
tùy chọn liên kết. Trong khi _DEBUG
liên quan đến các phiên bản gỡ lỗi đặc biệt của thư viện thời gian chạy như các cuộc gọi đến malloc
và free
. Sau đó NDEBUG
sẽ vô hiệu hóa các xác nhận.