2016-05-16 40 views
1

我想處理數據庫連接錯誤。如果CDatabase::Open(或CDatabase::OpenEx)失敗,則通常拋出CDBException。但有事。我無法處理它!未處理的CDBException,同時有一個適當的「趕上」

這裏是我的代碼:

try 
{ 
    CDatabase db; 
    db.OpenEx(L"DSN=INVALID_DSN;UID=noname", CDatabase::noOdbcDialog); 
    wprintf(L"Connection established.\n" 
      L"DSN used: %s\n" 
      L"DB name: %s\n", 
      db.GetConnect().GetBuffer(), 
      db.GetDatabaseName().GetBuffer()); 
    db.Close(); 
    puts("Connection closed."); 
} 
catch (CDBException& e) 
{ 
    e.GetErrorMessage(buf, BUF_SIZE); 
    wprintf(L"CDBException: %s\n", buf); 
} 
catch (CException& e) 
{ 
    e.GetErrorMessage(buf, BUF_SIZE); 
    wprintf(L"CException: %s\n", buf); 
} 
catch (std::exception& e) 
{ 
    printf("STD exception: %s\n", e.what()); 
} 
// this section is the only way to handle exception thrown by the CDatabase::OpenEx 
//catch (...) 
//{ 
// puts("Unknown exception"); 
//} 

如果最後catch的評論,我得到錯誤的通知:

**Unhandled exception at 0x76EAB727 in test-odbc.exe: Microsoft C++ exception: CDBException at memory location 0x004DF40C.**

我使用Visual Studio 2013(版本12.0.40629.00更新5)

回答

1

您將需要使用MFC特定的異常處理的宏:TRYCATCHEND_CATCH。 MFC異常僅爲指針,並且僅由特殊的宏刪除。

example here

編輯:內嵌例如:

TRY 
{ 
    // Do something to throw an exception. 
    AfxThrowUserException(); 
} 
CATCH(CException, e) 
{ 
    if (m_bPassExceptionsUp) 
     THROW_LAST(); 

    if (m_bReturnFromThisFunction) 
     return; 

    // Not necessary to delete the exception e. 
} 
END_CATCH 
1

看着MSDN文檔,他們(奇怪地)說要捕獲指向異常的指針,而不是引用:

https://msdn.microsoft.com/en-us/library/19b8k939.aspx

try 
{ 
} 
catch(CDBException* e) 
{ 
} 
+0

雖然此鏈接可以回答這個問題,最好是在這裏有答案的主要部件,並提供鏈接以供參考。如果鏈接頁面更改,則僅鏈接答案可能會失效 – Nehal

2

MFC 1.0於1992年發佈,針對C++編程語言的官方ISO/IEC語言規範6年前被批准。由於異常處理是過程後期固化的功能之一,MFC基於異常的(當時的)實現基於其框架。 Exception Handling in MFC與以下方式的異常處理有所不同:

  • MFC異常只能通過指針捕獲。範例「拋出價值,被(const)引用」捕獲尚未建立。
  • 最終異常處理程序必須執行清理MFC異常。

MFC提供的宏來實現它的異常處理(TRYCATCHAND_CATCHEND_CATCHTHROWTHROW_LAST),你將在現有的代碼中找到,但沒有要求在新代碼中使用它們。使用標準C++異常處理關鍵字可以實現相同的功能(有關說明,請參閱Exceptions: Converting from MFC Exception Macros)。

將此應用於代碼:

try { 
    CDatabase db; 
    db.OpenEx(L"DSN=INVALID_DSN;UID=noname", CDatabase::noOdbcDialog); 
    wprintf(L"Connection established.\n" 
      L"DSN used: %s\n" 
      L"DB name: %s\n", 
      db.GetConnect().GetBuffer(), 
      db.GetDatabaseName().GetBuffer()); 
    db.Close(); 
    puts("Connection closed."); 
} 
catch (CDBException* e) { // Catch by pointer 
    e->GetErrorMessage(buf, BUF_SIZE); 
    wprintf(L"CDBException: %s\n", buf); 
    // Dispose exception object; Do not use the delete keyword, because it can fail if 
    // the exception is not on the heap. 
    // Do not call Delete() in case you want to rethrow the exception. 
    e->Delete(); 
} 
catch (CException* e) { 
    e->GetErrorMessage(buf, BUF_SIZE); 
    wprintf(L"CException: %s\n", buf); 
    e->Delete(); 
} 
catch (const std::exception& e) { // Catch by const reference 
    printf("STD exception: %s\n", e.what()); 
} 
catch (...) { 
    // Only use after a 'catch(CException*)' clause to not leak MFC exception objects 
} 
相關問題