本系列第五部分聚焦 **錯誤處理**:如何分類上報、盡早發現、嚴格測試,構建健壯軟體的防線。
| 函數類別 | 特徵 | 錯誤上報方式 |
|---|---|---|
| 非 UI 函數 | 不直接與使用者互動 (工具函式、演算法、資料存取) | **回傳值** 帶錯誤碼;嚴禁彈視窗/寫日誌 (職責不清) |
| UI 函數 | 直接與使用者互動 (對話框、視窗處理) | **自行彈出警告** 並處理;不向上層拋回錯誤碼 |
通用錯誤處理函數:集中 `switch(errCode)` 處理,避免分散式 `if-else` 污染業務邏輯。
| 維度 | `ASSERT(expr)` | `if (!expr) return ERR;` |
|---|---|---|
| 編譯版本 | Debug 保留,Release **完全移除** (零開銷) | 所有版本保留 |
| 效能影響 | Release 無任何指令 | 永遠有分支預測/指令開銷 |
| 健壯性 | 僅開發期生效,Release 不攔截 | 全生命週期防護 |
| 適用對象 | **程式設計錯誤** (違反契約、邏輯 Bug) | **運行期錯誤** (資源耗盡、輸入無效、網路失敗) |
// 開發期斷言攔截程式錯誤,釋出版仍保留基本防護
ASSERT(pvToMem && pvFromMem); // Debug 攔截空指標
if (!pvToMem || !pvFromMem) { // Release 基本防護
return CM_POINT_IS_NULL;
}
原則:高頻/效能敏感 → 斷言 + 最小運行期檢查;一般函數 → 完整運行期檢查;Debug 版所有內部 DLL/EXE 必須帶斷言符號。
long cmMemCpy(void* pvTo, const void* pvFrom, size_t sz)
{
long lResult = CM_OK;
ASSERT(pvTo && pvFrom); // 開發期契約檢查
if (!pvTo || !pvFrom) { // 運行期基本防護
lResult = CM_POINT_IS_NULL;
goto END;
}
// ... 核心邏輯 ...
END:
return lResult;
}
錯誤處理的核心哲學是 **「分層防禦」**:
斷言不是「偷懶不寫檢查」,而是 **「精準區分程式錯誤與運行錯誤」** 的專業工具。正確使用斷言,能同時獲得開發期高敏感度與釋放版高效能,是成熟 C/C++ 工程師的標誌技能之一。