正确捕获 CDatabase::Close 异常
Correctly catching the CDatabase::Close exception
我想我会做一些关于缓存异常的挖掘。
根据这个问题 (C++ catching all exceptions) 的答案之一是:
[catch(...)
] will catch all C++ exceptions, but it should be considered bad design.
目前我使用过这种方法:
CPTSDatabase::~CPTSDatabase()
{
try
{
CloseDatabase();
}
catch(...)
{
}
}
void CPTSDatabase::CloseDatabase()
{
if (m_dbDatabase.IsOpen())
m_dbDatabase.Close();
}
我认为这是正确的方法,因为当我追踪到 CDatabase::Close()
时,它做了类似的事情:
// Disconnect connection
void CDatabase::Close()
{
ASSERT_VALID(this);
// Close any open recordsets
AfxLockGlobals(CRIT_ODBC);
TRY
{
while (!m_listRecordsets.IsEmpty())
{
CRecordset* pSet = (CRecordset*)m_listRecordsets.GetHead();
pSet->Close(); // will implicitly remove from list
pSet->m_pDatabase = NULL;
}
}
CATCH_ALL(e)
{
AfxUnlockGlobals(CRIT_ODBC);
THROW_LAST();
}
END_CATCH_ALL
AfxUnlockGlobals(CRIT_ODBC);
if (m_hdbc != SQL_NULL_HDBC)
{
RETCODE nRetCode;
AFX_SQL_SYNC(::SQLDisconnect(m_hdbc));
AFX_SQL_SYNC(::SQLFreeConnect(m_hdbc));
m_hdbc = SQL_NULL_HDBC;
_AFX_DB_STATE* pDbState = _afxDbState;
AfxLockGlobals(CRIT_ODBC);
ASSERT(pDbState->m_nAllocatedConnections != 0);
pDbState->m_nAllocatedConnections--;
AfxUnlockGlobals(CRIT_ODBC);
}
}
并且 CDatabase::Close
文档甚至没有说明任何有关抛出异常的信息。
链接的答案说明:
You can use c++11's new current_exception
mechanism.
鉴于我们正在使用 CDatabase
class,目前尚不清楚我们是否可以使用这种方法。
既然CDatabase::Close()
是用THROW_LAST
来抛出CDBException
,你就得用catch (CDBException* e)
。即使你不处理它,你仍然要 Delete
错误。直接调用CDatabase
方法的时候不妨这样做:
void CPTSDatabase::CloseDatabase()
{
try
{
if (m_dbDatabase.IsOpen())
m_dbDatabase.Close();
}
catch (CDBException* e)
{
//TRACE(L"DB error: " + e->m_strError);
e->Delete();
}
}
或使用
CPTSDatabase::~CPTSDatabase()
{
try { CloseDatabase(); }
catch (CDBException* e) { e->Delete(); }
catch(...) {}
}
因为在这段代码中并不清楚异常是从哪里来的。 catch(...) {}
将处理其他异常。一般来说 catch(...) {}
不推荐,因为它没有提供有用的信息,它只是说“出了点问题...”
仅当您在自己的代码中添加 throw
或使用 std
函数时才使用标准库异常。示例:
try { std::stoi("wrong argument"); }
catch (const std::exception& e) { TRACE("%s\n", e.what()); }
try { throw 123; }
catch (int i) { TRACE("%d\n", i); }
我想我会做一些关于缓存异常的挖掘。
根据这个问题 (C++ catching all exceptions) 的答案之一是:
[
catch(...)
] will catch all C++ exceptions, but it should be considered bad design.
目前我使用过这种方法:
CPTSDatabase::~CPTSDatabase()
{
try
{
CloseDatabase();
}
catch(...)
{
}
}
void CPTSDatabase::CloseDatabase()
{
if (m_dbDatabase.IsOpen())
m_dbDatabase.Close();
}
我认为这是正确的方法,因为当我追踪到 CDatabase::Close()
时,它做了类似的事情:
// Disconnect connection
void CDatabase::Close()
{
ASSERT_VALID(this);
// Close any open recordsets
AfxLockGlobals(CRIT_ODBC);
TRY
{
while (!m_listRecordsets.IsEmpty())
{
CRecordset* pSet = (CRecordset*)m_listRecordsets.GetHead();
pSet->Close(); // will implicitly remove from list
pSet->m_pDatabase = NULL;
}
}
CATCH_ALL(e)
{
AfxUnlockGlobals(CRIT_ODBC);
THROW_LAST();
}
END_CATCH_ALL
AfxUnlockGlobals(CRIT_ODBC);
if (m_hdbc != SQL_NULL_HDBC)
{
RETCODE nRetCode;
AFX_SQL_SYNC(::SQLDisconnect(m_hdbc));
AFX_SQL_SYNC(::SQLFreeConnect(m_hdbc));
m_hdbc = SQL_NULL_HDBC;
_AFX_DB_STATE* pDbState = _afxDbState;
AfxLockGlobals(CRIT_ODBC);
ASSERT(pDbState->m_nAllocatedConnections != 0);
pDbState->m_nAllocatedConnections--;
AfxUnlockGlobals(CRIT_ODBC);
}
}
并且 CDatabase::Close
文档甚至没有说明任何有关抛出异常的信息。
链接的答案说明:
You can use c++11's new
current_exception
mechanism.
鉴于我们正在使用 CDatabase
class,目前尚不清楚我们是否可以使用这种方法。
既然CDatabase::Close()
是用THROW_LAST
来抛出CDBException
,你就得用catch (CDBException* e)
。即使你不处理它,你仍然要 Delete
错误。直接调用CDatabase
方法的时候不妨这样做:
void CPTSDatabase::CloseDatabase()
{
try
{
if (m_dbDatabase.IsOpen())
m_dbDatabase.Close();
}
catch (CDBException* e)
{
//TRACE(L"DB error: " + e->m_strError);
e->Delete();
}
}
或使用
CPTSDatabase::~CPTSDatabase()
{
try { CloseDatabase(); }
catch (CDBException* e) { e->Delete(); }
catch(...) {}
}
因为在这段代码中并不清楚异常是从哪里来的。 catch(...) {}
将处理其他异常。一般来说 catch(...) {}
不推荐,因为它没有提供有用的信息,它只是说“出了点问题...”
仅当您在自己的代码中添加 throw
或使用 std
函数时才使用标准库异常。示例:
try { std::stoi("wrong argument"); }
catch (const std::exception& e) { TRACE("%s\n", e.what()); }
try { throw 123; }
catch (int i) { TRACE("%d\n", i); }