Reputation: 89
I'm trying to handle DB connection error. If the CDatabase::Open
(or the CDatabase::OpenEx
) fails, the CDBException
is normally thrown. But there's the thing. I can't handle it!
Here's my code:
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");
//}
If the last catch
is commented, I get error notification:
I use Visual Studio 2013 (Version 12.0.40629.00 Update 5)
Upvotes: 2
Views: 1330
Reputation: 51413
MFC 1.0 was released in 1992, 6 years before the official ISO/IEC language specification for the C++ Programming Language was ratified. With exception handling being one of the features that solidified late in the process, MFC based its framework on the (then current) implementation for exceptions. Exception Handling in MFC differs from today's exception handling in the following ways:
MFC provides macros to implement its exception handling (TRY
, CATCH
, AND_CATCH
, END_CATCH
, THROW
, THROW_LAST
) which you will find in existing code, but there is no requirement to use them in new code. The same functionality can be implemented using Standard C++ exception handling keywords (see Exceptions: Converting from MFC Exception Macros for instructions).
Applying this to your code:
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
}
Upvotes: 2
Reputation: 141
Looking at the MSDN docs, they (strangely) say to catch a pointer to the exception, not a reference:
https://msdn.microsoft.com/en-us/library/19b8k939.aspx
try
{
}
catch(CDBException* e)
{
}
Upvotes: 1
Reputation: 18431
You will need to use MFC specific exception handling macros: TRY
, CATCH
, and END_CATCH
. MFC exceptions are pointer-only, and are deleted by special macros only.
See example here
EDIT: Inline example:
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
Upvotes: 1