Is there a concise location that documents all known ADO Leaks and appropriate hot fixes?

EDN Admin

Well-known member
Joined
Aug 7, 2010
Messages
12,794
Location
In the Machine
Iâve been looking for the root cause of memory leaks in my code and keep coming back to ADO. The code is acting as if there was some sort of reference counting issue within the ADO components. Iâve been over this code dozens of times over the
last few days and was not able to locate a reference counting issue.
OS: Windows Server 2008 R2, all updates applied as of 11/30/2011
MSADO15.DLL version 6.1.7600.16688
MSADCE.DLL version 6.1.7600.20595

I have found a number of hot fixes for memory leaks in ADO, but have not found a hot fix (or combination of) that resolves all of my leaks.
KB978042 (http://support.microsoft.com/kb/978042) You use the Microsoft ActiveX Data Objects Library (Msado15.dll) to access the ConnectionString property of the ADODB.Connection object.
My application does not retrieve the ADO connection string (so the hot fix kb978042 should not apply).
KB978155(http://support.microsoft.com/kb/978155) You have an SQL table that contains an identity column. You start an application that uses a Microsoft ActiveX Data Objects (ADO) client-side Recordset object to access the SQL database. This application calls
the UpdateBatch method to insert several rows into the table.
All of the items in KB978155 applied to my application and I was experiencing a leak when UpdateBatch() was called until I applied this hotfix.

The following test code demonstrates the leaks Iâm seeing.
When the function was executed 10,000 times private bytes for the process went from 1,839,104 bytes to 2,920,448.
HRESULT CADO_LeakDlg::OpenRSWithCommand( )
{
<span style="white-space:pre USES_CONVERSION;
<span style="white-space:pre HRESULT hr = S_OK;
<span style="white-space:pre CComPtr<ADO::ADOConnection><span style="white-space:pre
spConnection;
<span style="white-space:pre CComPtr<ADOCommand><span style="white-space:pre
spADOCmd;
<span style="white-space:pre CComPtr<ADORecordset><span style="white-space:pre
spRS;
<span style="white-space:pre BSTR bstrConnectionString<span style="white-space:pre
= ::SysAllocString( WSZ_CONNECTION_STRING );
<span style="white-space:pre BSTR bstrUser<span style="white-space:pre
= ::SysAllocString( WSZ_USER_STRING );
<span style="white-space:pre BSTR bstrPassword<span style="white-space:pre
= ::SysAllocString( WSZ_PWD_STRING );

<span style="white-space:pre try
<span style="white-space:pre {
<span style="white-space:pre // Open the ADO Connection
<span style="white-space:pre hr = OpenConnection( spConnection, bstrConnectionString, bstrUser, bstrPassword );
<span style="white-space:pre if(spConnection)
<span style="white-space:pre {
<span style="white-space:pre if(SUCCEEDED(hr))
<span style="white-space:pre {
<span style="white-space:pre // Create the ADO Command object
<span style="white-space:pre hr = CoCreateInstance(CLSID_CADOCommand, NULL,
<span style="white-space:pre CLSCTX_INPROC_SERVER, IID_IADOCommand, (LPVOID *)&spADOCmd);
<span style="white-space:pre _bstr_t stored_proc = _T("MySchema.MyStoredProc");

<span style="white-space:pre // Set the active connection
<span style="white-space:pre hr = spADOCmd->putref_ActiveConnection( spConnection );
<span style="white-space:pre hr = spADOCmd->put_CommandText(stored_proc);
<span style="white-space:pre hr = spADOCmd->put_CommandType(adCmdStoredProc);

<span style="white-space:pre // Create the parameters for my stored procedure
<span style="white-space:pre _variant_t vFamilyID<span style="white-space:pre
= 1L;
<span style="white-space:pre _variant_t vUniqueID<span style="white-space:pre
= 2L;
<span style="white-space:pre _variant_t vMemberID<span style="white-space:pre
= 2L;
<span style="white-space:pre
<span style="white-space:pre _variant_t vMemberIID(L"{F4DDF1B8-BB56-4293-873F-5D1B6357C30C}");

<span style="white-space:pre CComPtr<ADOParameter> spParam1 = NULL;
<span style="white-space:pre CComPtr<ADOParameter> spParam2 = NULL;
<span style="white-space:pre CComPtr<ADOParameter> spParam3 = NULL;
<span style="white-space:pre CComPtr<ADOParameter> spParam4 = NULL;

<span style="white-space:pre CComPtr<ADOParameters> spParams = NULL;
<span style="white-space:pre
<span style="white-space:pre hr = spADOCmd->get_Parameters( &spParams );

<span style="white-space:pre hr = spADOCmd->CreateParameter( _bstr_t(_T("FamilyID")), adInteger,
<span style="white-space:pre adParamInput, 4, vFamilyID, &spParam1);
<span style="white-space:pre hr = spParams->Append(spParam1);
<span style="white-space:pre hr = spADOCmd->CreateParameter( _bstr_t(_T("UniqueID")), adInteger,
<span style="white-space:pre adParamInput, 4, vUniqueID, &spParam2);
<span style="white-space:pre hr = spParams->Append(spParam2);
<span style="white-space:pre hr = spADOCmd->CreateParameter( _bstr_t(_T("MemberIID")), adGUID,
<span style="white-space:pre adParamInput, 255, vMemberIID, &spParam3);
<span style="white-space:pre hr = spParams->Append(spParam3);
<span style="white-space:pre hr = spADOCmd->CreateParameter( _bstr_t(_T("MemberID")), adInteger,
<span style="white-space:pre adParamInput, 4, vMemberID, &spParam4);
<span style="white-space:pre hr = spParams->Append(spParam4);

<span style="white-space:pre // Create the ADO record set object
<span style="white-space:pre CComPtr<ADORecordset> spRS;
<span style="white-space:pre hr = CoCreateInstance(CLSID_CADORecordset, NULL, CLSCTX_INPROC_SERVER,
<span style="white-space:pre IID_IADORecordset, (LPVOID *)&spRS);

<span style="white-space:pre _variant_t vtSource = spADOCmd;
<span style="white-space:pre _variant_t vNull;<span style="white-space:pre

<span style="white-space:pre V_VT(&vNull) = VT_ERROR;
<span style="white-space:pre V_ERROR(&vNull) = DISP_E_PARAMNOTFOUND;
<span style="white-space:pre hr = spRS->put_CursorLocation( adUseClient );
<span style="white-space:pre // Open the recordset with the ADO command object (passed in as vtSource)
<span style="white-space:pre hr = spRS->Open( vtSource, vNull, adOpenKeyset, adLockOptimistic,
<span style="white-space:pre adCmdStoredProc );
<span style="white-space:pre if(SUCCEEDED(hr))
<span style="white-space:pre {
<span style="white-space:pre VARIANT_BOOL<span style="white-space:pre
vbEOF;
<span style="white-space:pre hr = spRS->get_EOF(&vbEOF);
<span style="white-space:pre }

<span style="white-space:pre // Should not *have* to do this, as the smart pointers should release
<span style="white-space:pre // the object when it goes out of scope.
<span style="white-space:pre // Setting to NULL Should release the last reference to the ADO paramx object.
<span style="white-space:pre spParam1 = NULL;
<span style="white-space:pre spParam2 = NULL;
<span style="white-space:pre spParam3 = NULL;
<span style="white-space:pre spParam4 = NULL;
<span style="white-space:pre spParams = NULL;

<span style="white-space:pre // Setting to NULL Should release the last reference to the ADO params object.
<span style="white-space:pre spParams = NULL;

<span style="white-space:pre // Setting to NULL Should release the last reference to the ADO command object.
<span style="white-space:pre spADOCmd = NULL;
<span style="white-space:pre spRS->Close();
<span style="white-space:pre spRS = NULL;
<span style="white-space:pre spConnection->Close();<span style="white-space:pre
// Close the connection
<span style="white-space:pre }
<span style="white-space:pre spConnection = NULL;<span style="white-space:pre
// Release the connection COM object
<span style="white-space:pre }
<span style="white-space:pre }
<span style="white-space:pre catch(...)
<span style="white-space:pre {
<span style="white-space:pre }

<span style="white-space:pre if( bstrConnectionString )
<span style="white-space:pre ::SysFreeString( bstrConnectionString );
<span style="white-space:pre bstrConnectionString = NULL;
<span style="white-space:pre if( bstrUser )
<span style="white-space:pre ::SysFreeString( bstrUser );
<span style="white-space:pre bstrUser = NULL;
<span style="white-space:pre if( bstrPassword )
<span style="white-space:pre ::SysFreeString( bstrPassword );
<span style="white-space:pre bstrPassword = NULL;

<span style="white-space:pre return hr;
}

HRESULT CADO_LeakDlg::OpenConnection( CComPtr<ADO::ADOConnection> &spConnection,
BSTR bstrConnectionString, BSTR bstrUser, BSTR bstrPassword )
{
<span style="white-space:pre HRESULT hr = S_OK;

<span style="white-space:pre hr = CoCreateInstance(CLSID_CADOConnection, NULL,
<span style="white-space:pre CLSCTX_INPROC_SERVER, IID_IADOConnection, (void **)&spConnection);

<span style="white-space:pre if(FAILED(hr))
<span style="white-space:pre return hr;<span style="white-space:pre
// Failed to create the connection object

<span style="white-space:pre hr = spConnection->Open( bstrConnectionString, bstrUser, bstrPassword, adOpenUnspecified );
<span style="white-space:pre return hr;
}



<br/>

View the full article
 
Back
Top