Microsoft Knowledge Base Email Alertz

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.

Search KbAlertz

Advanced Search

Receive Microsoft Knowledge Base articles by E-Mail?

Every night we scan the Microsoft Knowledge Base. If technologies you're interested in are updated, we'll send you an e-mail. You only get one e-mail a day, and only when new articles are added.

Click here to create a
FREE account
Already have an account?
[Click here to Login]











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

On This Page

SYMPTOMS

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.

CAUSE

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.

RESOLUTION

Call VariantClear on the vValue member of every DBPROP structure in every DBPROP array before freeing the DBPROP array.

STATUS

This behavior is by design.

MORE INFORMATION

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
Keywords: 
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