ควรใช้ตัวประมวลผลล่วงหน้าชุดใดเพื่อระบุส่วนการดีบักของรหัส
ใช้#ifdef _DEBUGหรือ#ifndef NDEBUGหรือมีวิธีที่ดีกว่าที่จะทำเช่น#define MY_DEBUG?
ฉันคิดว่า_DEBUGเป็น Visual Studio เฉพาะมาตรฐาน NDEBUG หรือไม่
ควรใช้ตัวประมวลผลล่วงหน้าชุดใดเพื่อระบุส่วนการดีบักของรหัส
ใช้#ifdef _DEBUGหรือ#ifndef NDEBUGหรือมีวิธีที่ดีกว่าที่จะทำเช่น#define MY_DEBUG?
ฉันคิดว่า_DEBUGเป็น Visual Studio เฉพาะมาตรฐาน NDEBUG หรือไม่
คำตอบ:
Visual Studio กำหนด_DEBUGเมื่อคุณระบุ/MTdหรือ/MDdตัวเลือกNDEBUGปิดการใช้งานการยืนยันมาตรฐาน C ใช้พวกเขาในเวลาที่เหมาะสมเช่น_DEBUGถ้าคุณต้องการรหัสแก้จุดบกพร่องของคุณเพื่อให้สอดคล้องกับเทคนิค MS CRT แก้จุดบกพร่องและถ้าคุณต้องการเพื่อให้สอดคล้องกับNDEBUGassert()
หากคุณกำหนดมาโครการดีบักของคุณเอง (และคุณไม่แฮกคอมไพเลอร์หรือรันไทม์ C) ให้หลีกเลี่ยงการเริ่มต้นชื่อด้วยเครื่องหมายขีดล่างเนื่องจากสิ่งเหล่านี้สงวนไว้
เป็นมาตรฐาน NDEBUG หรือไม่
ใช่มันเป็นแมโครมาตรฐานที่มีความหมาย "Not Debug" สำหรับ C89, C99, C ++ 98, C ++ 2003, C ++ 2011, C ++ 2014 ไม่มี_DEBUGมาโครในมาตรฐาน
มาตรฐาน C ++ 2003 ส่งผู้อ่านไปที่ "หน้า 326" ที่ "17.4.2.1 ส่วนหัว" ถึงมาตรฐาน C
NDEBUG นั้นคล้ายกันกับนี่เหมือนกับไลบรารี C มาตรฐาน
ใน C89 (โปรแกรมเมอร์ C เรียกว่ามาตรฐานนี้เป็นมาตรฐาน C) ในส่วน "4.2 DIAGNOSTICS"
http://port70.net/~nsz/c/c89/c89-draft.html
ถ้า NDEBUG ถูกกำหนดให้เป็นชื่อแมโครที่จุดในไฟล์ต้นฉบับที่มีอยู่แมโคร assert จะถูกกำหนดอย่างง่าย ๆ ดังนี้
#define assert(ignore) ((void)0)
หากดูความหมายของ_DEBUGมาโครใน Visual Studio
https://msdn.microsoft.com/en-us/library/b0084kay.aspx
จะเห็นได้ว่ามาโครนี้ถูกกำหนดโดยอัตโนมัติโดยเวอร์ชันไลบรารีรันไทม์ภาษาของคุณ
ฉันพึ่งพาNDEBUGเพราะมันเป็นพฤติกรรมเดียวที่มีมาตรฐานในคอมไพเลอร์และการใช้งาน (ดูเอกสารประกอบสำหรับแมโครยืนยันมาตรฐาน) ตรรกะเชิงลบคือความเร็วในการอ่านเล็กน้อย แต่เป็นสำนวนทั่วไปที่คุณสามารถปรับให้เข้ากับได้อย่างรวดเร็ว
การพึ่งพาบางสิ่งเช่น_DEBUGนั้นก็คือการพึ่งพารายละเอียดการใช้งานของคอมไพเลอร์และการใช้งานไลบรารี คอมไพเลอร์อื่น ๆ อาจจะหรืออาจจะไม่เลือกแบบแผนเดียวกัน
ตัวเลือกที่สามคือการกำหนดแมโครของคุณเองสำหรับโครงการของคุณซึ่งค่อนข้างสมเหตุสมผล การมีมาโครของคุณเองจะช่วยให้คุณพกพาระหว่างการติดตั้งใช้งานและช่วยให้คุณสามารถเปิดหรือปิดการใช้งานรหัสการดีบักได้อย่างอิสระ แม้ว่าโดยทั่วไปแล้วฉันแนะนำไม่ให้มีคลาสที่แตกต่างกันของข้อมูลการดีบักที่เปิดใช้งานในเวลารวบรวมเนื่องจากจะทำให้จำนวนการกำหนดค่าที่คุณต้องสร้าง (และทดสอบ) เพิ่มขึ้นเพื่อประโยชน์เล็ก ๆ น้อย ๆ
ด้วยตัวเลือกใด ๆ เหล่านี้หากคุณใช้รหัสของบุคคลที่สามเป็นส่วนหนึ่งของโครงการของคุณคุณจะต้องทราบถึงข้อตกลงที่ใช้
#if !defined(NDEBUG)<- @HostileFork นั่นไม่ใช่สิ่งที่คุณหมายถึงเหรอ? #ifไม่ใช่#ifdefเหรอ
#ifdef NDEBUG... #if !defined(NDEBUG)แต่แล้วเรียกความสนใจเป็นพิเศษกับตรรกะเชิงลบด้วยไม่งั้นมันก็ยากที่จะจับตัว n ใน#ifndef NDEBUG"
แมโครNDEBUGควบคุมว่าassert()ข้อความสั่งทำงานหรือไม่
ในมุมมองของฉันที่แยกจากการดีบักอื่น ๆ - ดังนั้นฉันใช้สิ่งอื่นที่ไม่ใช่ NDEBUGการควบคุมข้อมูลการดีบักในโปรแกรม สิ่งที่ฉันใช้แตกต่างกันไปขึ้นอยู่กับกรอบที่ฉันทำงานด้วย ระบบที่แตกต่างกันมีแมโครที่เปิดใช้งานที่แตกต่างกันและฉันใช้สิ่งที่เหมาะสม
หากไม่มีกรอบฉันจะใช้ชื่อโดยไม่มีขีดเส้นใต้ ผู้ที่มีแนวโน้มที่จะถูกสงวนไว้ที่ 'การใช้งาน' และฉันพยายามหลีกเลี่ยงปัญหาเกี่ยวกับการชนชื่อ - สองเท่าดังนั้นเมื่อชื่อเป็นมาโคร
#ifรหัสที่ควบคุมได้ในอีกประเภทหนึ่ง assert(huge_object.IsValid());อาจช้าในขณะที่assert(ptr != nullptr);อาจไม่ใช่ ฉันเห็นด้วยกับโจนาธานว่าการบันทึกและการติดตามควรจะแตกต่างจากการยืนยันอย่างน้อยในโครงการขนาดใหญ่ แต่ฉันไม่คิดว่าการบันทึกหรือการสืบค้นกลับเป็นรหัสดีบักซึ่งเป็นสาเหตุที่ฉันขอคำชี้แจง
มีความสอดคล้องและมันไม่สำคัญว่าจะเป็นที่หนึ่ง นอกจากนี้หากมีเหตุผลบางอย่างที่คุณต้องทำงานร่วมกับโปรแกรมหรือเครื่องมืออื่นโดยใช้ตัวระบุ DEBUG บางตัวมันก็สามารถทำได้
#ifdef THEIRDEBUG
#define MYDEBUG
#endif //and vice-versa
น่าเสียดายที่DEBUGมีการใช้งานมากเกินไป ตัวอย่างเช่นแนะนำให้สร้างและบันทึกไฟล์ pdb สำหรับการสร้าง RELEASE เสมอ ซึ่งหมายถึงหนึ่งใน-Zxแฟล็กและ-DEBUGตัวเลือกลิงก์ ในขณะที่_DEBUGเกี่ยวข้องกับการแก้ปัญหารุ่นพิเศษของไลบรารีรันไทม์เช่นโทรไปและmalloc freeจากนั้นNDEBUGจะปิดใช้งานการยืนยัน