未处理的CDBException同时具有适当的" catch"

时间:2016-05-16 09:20:46

标签: c++ database exception mfc

我试图处理数据库连接错误。如果CDatabase::Open(或CDatabase::OpenEx)失败,则通常会抛出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 Update 5)

3 个答案:

答案 0 :(得分:2)

MFC 1.0于1992年发布,距离C ++编程语言的官方ISO / IEC语言规范获得批准已有6年。由于异常处理是流程后期固化的功能之一,因此MFC将其框架基于(当时)异常实现。 Exception Handling in MFC与今天的异常处理有以下不同之处:

  • MFC异常只能通过指针捕获。范式“按价值抛出,赶上(常)参考”尚未建立。
  • 最终的异常处理程序必须执行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
}

答案 1 :(得分:1)

查看MSDN文档,他们(奇怪地)说要捕获指向异常的指针,而不是引用:

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

try
{
}
catch(CDBException* e)
{
}

答案 2 :(得分: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