FIX: Deleting CRecordset Object Before Closing ItID: Q113815
|
If a CDatabase object is allocated and then passed into a CRecordset constructor the user may notice a memory leak if the CRecordset is deleted before calling CRecordset::Close(). Not only will memory leak, but the following ODBC error may eventually occur when using snapshots (or more specifically, when using the cursor library):
General Error: Unable to create file buffer
State:S1000
A bug in the CRecordset destructor prevents the ::SQLFreeStmt() from getting called for the ODBC statement handle (HSTMT) used by the CRecordset object.
To work around the problem, make sure that CRecordset::Close() is called before it is deleted. One way to handle this is to put a call to CRecordset::Close() in the destructor of the CRecordset-derived class.
Microsoft has confirmed this to be a bug in the products listed at the beginning of this article. This bug was corrected in MFC version 3.0, included with Visual C++, 32-bit Edition, version 2.0.
The CRecordset destructor has the following code:
CRecordset::~CRecordset()
{
if (!m_bRecordsetDb)
m_pDatabase = NULL;
ASSERT_VALID(this);
TRY
{
Close();
if (m_bRecordsetDb)
{
delete m_pDatabase;
m_pDatabase = NULL;
}
}
...
The m_bRecordsetDb is a flag that the CRecordset class uses to tell
whether the CRecordset created the CDatabase object or whether it was
passed to the CRecordset in the constructor. If a program passes in
the CDatabase pointer to the CRecordset, looking at the code you can
see that m_pDatabase will be set to NULL. Unfortunately this causes
a problem when Close() is called later in the function.
In CRecordset::Close() the following lines determine whether the
HSTMT allocated by the CRecordset needs to be freed:
if (m_pDatabase != SQL_NULL_HDBC)
{
AFX_SQL_SYNC(::SQLFreeStmt(m_hstmtUpdate, SQL_DROP));
}
Since m_pDatabase has been set to NULL and the CDatabase object still
exists, we run into a problem because SQL_NULL_HDBC is equal to NULL.
Thus, the statement handle is never freed although the CRecordset
goes away. This normally isn't too much of a problem because
statement handles get freed when a connection goes away. However, if
you are re-using a CDatabase for multiple CRecordset objects, many
allocated HSTMTs will accumulate.
Additional query words: 1.50 2.50 2.51 odbc
Keywords : kb16bitonly kbDatabase kbMFC kbODBC kbVC
Version : 1.50 1.51
Platform : WINDOWS
Issue type :
Last Reviewed: August 3, 1999