首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C++ 例外處理:try/catch 捕捉與 MFC 例外機制完整解析

     編輯:關於C語言

軟體必然出錯:邏輯錯誤、資源耗盡、使用者操作失誤、外部環境變化。C++ `try`/`catch`/`throw` 機制配合 MFC 例外類別 (`CException`、`CMemoryException`、`CFileException` 等),提供結構化錯誤處理。本文對比傳統錯誤碼與例外處理,示範標準與 MFC 例外捕捉模式,並說明資源清理 (RAII) 關鍵。

傳統錯誤碼 vs 例外處理


// 傳統:每層檢查返回值
BOOL ReadData() {
    FILE* f = fopen("data.dat", "r");
    if (!f) return FALSE;
    if (fread(buf, 1, 1024, f) != 1024) { fclose(f); return FALSE; }
    fclose(f); return TRUE;
}
void PrintData() { for (int i=0;i<1024;i++) printf("%x ", buf[i]); } // 隱患:buf 可能 NULL

呼叫端若忘記檢查 `ReadData()` 返回值,`PrintData()` 存取野指標 → 崩潰。

C++ 標準例外處理


void ReadData() {
    std::ifstream fs("data.dat", std::ios::binary);
    if (!fs) throw std::runtime_error("Open failed");
    fs.read(buf, 1024);
    if (!fs) throw std::runtime_error("Read failed");
}
void PrintData() {
    try {
        ReadData();
        for (int i=0;i<1024;i++) printf("%x ", buf[i]);
    } catch (const std::exception& e) {
        AfxMessageBox(CString(e.what()));
    }
}

MFC 例外機制

  • 所有例外衍生自 `CException`
  • 常用類別:`CMemoryException` (記憶體不足)、`CFileException` (檔案錯誤)、`CArchiveException` (序列化)、`CNotSupportedException` (不支援操作)、`COleException` (OLE/COM 錯誤)、`CDaoException`/`CDBException` (資料庫)
  • 拋出:`AfxThrowMemoryException()`、`AfxThrowFileException(err, ...)` 或 `throw new CFileException(...)`
  • 捕捉:`catch (CMemoryException* e)`、`catch (CFileException* e)`、**記得 `e->Delete()`** 釋放例外物件

MFC 例外捕捉標準模式


try {
    // 可能拋出例外的代碼
    CFile file(_T("data.dat"), CFile::modeRead);
    file.Read(buf, 1024);
}
catch (CFileException* e) {
    TCHAR szErr[256];
    e->GetErrorMessage(szErr, 256);
    AfxMessageBox(szErr);
    e->Delete();  // 必須釋放
}
catch (CMemoryException* e) {
    AfxMessageBox(_T("記憶體不足"));
    e->Delete();
}
catch (CException* e) {  // 兜底
    e->ReportError();    // 顯示標準錯誤訊息
    e->Delete();
}

RAII:資源獲取即初始化,例外安全的關鍵

區域物件析構函數在堆疊展開時自動執行,確保資源釋放:

  • 檔案:`CFile`、`std::ifstream` 析構自動 `close`
  • 記憶體:`std::vector`、`std::unique_ptr`、`CComPtr` 析構自動 `delete`/`Release`
  • 鎖:`CSingleLock`/`std::lock_guard` 析構自動 `Unlock`
  • GDI 物件:`CGdiObject` 衍生類析構自動 `DeleteObject`

鐵律:裸指標擁有權必須交給 RAII 包裝器,禁止在 `try` 區塊中手動 `new`/`delete` 配對。

MFC 特有:`AFX_MANAGE_STATE` 與 DLL 邊界

在 DLL 中拋出 MFC 例外跨越模組邊界需注意模組狀態管理,建議在 DLL 介面函數入口加入 `AFX_MANAGE_STATE(AfxGetStaticModuleState())`,並在 EXE 端捕捉 `CException*`。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved