Microsoft Knowledge Base Article
This article contents is Microsoft Copyrighted material.
©2005-©2007 Microsoft Corporation. All rights reserved.
Terms
of Use |
Trademarks
Article ID: 293349 - Last Review: May 12, 2003 - Revision: 2.1
PRB: Retrieving Properties with OLE DB May Cause Memory Leak
This article was previously published under Q293349
Whenever an OLE DB consumer application retrieves properties from the provider, it is the responsibility of the consumer application to free the memory associated with the property structures that the provider returns.
In some cases, however, freeing the property structures alone, as described in the OLE DB documentation, is not sufficient. Retrieving and freeing the properties will cause a memory leak in this case.
The
DBPROPSET structures returned to the client by the provider contain a pointer to an array of
DBPROP structures. The
DBPROP structures have a
VARIANT member called
vValue. Because the
vValue member could contain a pointer to a
BSTR or other allocated memory on output, the
vValue member should be cleared by the consumer application by calling the
VariantClear function. The OLE DB documentation does not specify this.
Call
VariantClear on the
vValue member of every
DBPROP structure in every
DBPROP array before freeing the
DBPROP array.
This behavior is by design.
The following OLE DB functions return property information to the consumer:
- IDBProperties::GetProperties
- IRowsetIndex::GetIndexInfo
- ICommandProperties::GetProperties
- IRowsetInfo::GetProperties
- ISessionProperties::GetProperties
Steps to Reproduce Behavior
The following sample code demonstrates the code that will leak memory:
#include <oledb.h>
#include <oledberr.h>
#include <msdasc.h>
#define DBINITCONSTANTS
#include <msdasc.h>
int main(int argc, TCHAR * argv[])
{
IDataInitialize* pIDataInitialize = NULL;
IDBInitialize* pIDBInitialize = NULL;
IDBProperties* pIDBProperties = NULL;
int iLoopMax = 10000;
int iLoop;
UINT iSet;
DBPROPSET* pPropsets = NULL;
unsigned long cPropertyIDSets = 0 ;
unsigned long cPropertySets = 0 ;
DBPROPIDSET rgPropertyIDSets[1];
HRESULT hr;
//If needed, change the connection string here.
OLECHAR* wszInitString = L"Provider=SQLOLEDB.1;User ID=sa;Initial Catalog=pubs;Data Source=(local);";
hr = CoInitialize(NULL);
hr = CoCreateInstance( CLSID_MSDAINITIALIZE,
NULL,
CLSCTX_INPROC_SERVER,
IID_IDataInitialize,
( void ** ) & pIDataInitialize );
hr = pIDataInitialize->GetDataSource(NULL, CLSCTX_INPROC_SERVER, wszInitString,
IID_IDBInitialize, ( IUnknown ** ) & pIDBInitialize );
hr = pIDBInitialize->Initialize();
hr = pIDBInitialize->QueryInterface(IID_IDBProperties, (void**) &pIDBProperties);
rgPropertyIDSets[0].rgPropertyIDs = NULL ;
rgPropertyIDSets[0].cPropertyIDs = 0 ;
rgPropertyIDSets[0].guidPropertySet = DBPROPSET_DATASOURCE;
for (iLoop = 0; iLoop < iLoopMax; iLoop++)
{
hr = pIDBProperties->GetProperties ( cPropertyIDSets,
rgPropertyIDSets,
&cPropertySets,
&pPropsets) ;
for (iSet = 0; iSet < cPropertySets; iSet++ )
{
DBPROP * pr = pPropsets[iSet].rgProperties;
//NOTE :Uncomment the following lines to remove the memory leak
//int iProp;
//for (iProp = 0; iProp < pPropsets[iSet].cProperties;iProp++)
//{
// VariantClear( &(pr[iProp].vValue) );
//}
CoTaskMemFree(pr);
}
CoTaskMemFree(pPropsets);
Sleep(1);
}
hr = pIDBInitialize->Uninitialize();
if (pIDBProperties)
{
pIDBProperties->Release();
}
if (pIDBInitialize)
{
pIDBInitialize->Release();
}
if (pIDataInitialize)
{
pIDataInitialize->Release();
}
return 0 ;
}
To free the memory correctly, uncomment the loop in the code above to free each individual
VARIANT member before freeing the
DBPROP array.
APPLIES TO
- Microsoft OLE DB 2.0
- Microsoft OLE DB 2.1
- Microsoft OLE DB 2.5
- Microsoft OLE DB 2.6
- Microsoft Data Access Components 2.7
| kbconsumer kbdatabase kbprb KB293349 |
Community Feedback System
Very often, it takes hours to solve a problem. Very often, you've looked high
and low, and have tried a lot of solutions. When you finally found it, chances
are, it was because someone else helped you. Here's your chance to give back.
Use our community feedback tool to let others know what worked for you and what
didn't.
Please also understand that the community feedback system is not warranted to be
correct, it's simply a system that we've built to let people try and help each
other. If something in a feedback response doesn't make sense to you, or you're
not comfortable making changes that the feedback talks about (like registry
edits), please consult a professional.
Thank you for using kbAlertz.com Feedback System.
-- Scott Cate