คุณควรใช้ทั้งสองอย่าง การยืนยันมีไว้เพื่อความสะดวกของคุณในฐานะผู้พัฒนา ข้อยกเว้นจับสิ่งที่คุณพลาดหรือไม่คาดคิดระหว่างรันไทม์
ฉันชอบฟังก์ชั่นการรายงานข้อผิดพลาดของคนกะล่อนแทนที่จะเป็นการยืนยันแบบเดิม ๆ พวกเขาทำตัวเหมือนยืนยันคำสั่ง แต่แทนที่จะหยุดโปรแกรมพวกเขากลับส่งคืนค่าและปล่อยให้โปรแกรมดำเนินการต่อ มันทำงานได้ดีอย่างน่าประหลาดใจและเป็นโบนัสที่คุณจะได้เห็นว่าเกิดอะไรขึ้นกับโปรแกรมที่เหลือของคุณเมื่อฟังก์ชันไม่ส่งคืน "สิ่งที่ควรจะเป็น" หากเกิดปัญหาคุณจะทราบว่าการตรวจสอบข้อผิดพลาดของคุณมีความหละหลวมอยู่ที่อื่น
ในโครงการสุดท้ายของฉันฉันใช้รูปแบบของฟังก์ชันเหล่านี้เพื่อใช้การตรวจสอบเงื่อนไขเบื้องต้นและหากหนึ่งในนั้นล้มเหลวฉันจะพิมพ์การติดตามสแต็กไปยังล็อกไฟล์ แต่ยังคงทำงานต่อไป ช่วยฉันประหยัดเวลาในการดีบักจำนวนมากเมื่อคนอื่น ๆ พบปัญหาเมื่อเรียกใช้งานการสร้างการแก้ไขข้อบกพร่องของฉัน
#ifdef DEBUG
#define RETURN_IF_FAIL(expr) do { \
if (!(expr)) \
{ \
fprintf(stderr, \
"file %s: line %d (%s): precondition `%s' failed.", \
__FILE__, \
__LINE__, \
__PRETTY_FUNCTION__, \
#expr); \
::print_stack_trace(2); \
return; \
}; } while(0)
#define RETURN_VAL_IF_FAIL(expr, val) do { \
if (!(expr)) \
{ \
fprintf(stderr, \
"file %s: line %d (%s): precondition `%s' failed.", \
__FILE__, \
__LINE__, \
__PRETTY_FUNCTION__, \
#expr); \
::print_stack_trace(2); \
return val; \
}; } while(0)
#else
#define RETURN_IF_FAIL(expr)
#define RETURN_VAL_IF_FAIL(expr, val)
#endif
หากฉันต้องการการตรวจสอบรันไทม์ของอาร์กิวเมนต์ฉันจะทำสิ่งนี้:
char *doSomething(char *ptr)
{
RETURN_VAL_IF_FAIL(ptr != NULL, NULL); // same as assert(ptr != NULL), but returns NULL if it fails.
// Goes away when debug off.
if( ptr != NULL )
{
...
}
return ptr;
}