Microsoft KB Archive/253236

{|
 * width="100%"|

BUG: ATL OLE DB CDataSource::OpenFromFileName Has Memory Leak

 * }

-

The information in this article applies to:


 * The Microsoft Active Template Library (ATL) 3.0, used with:
 * Microsoft Visual C++, 32-bit Editions, version 6.0 SP3

-

SYMPTOMS
The CDataSource::OpenFromFileName function is used to open an OLE DB data source from a file with a .udl extension. Repeatedly calling this function in a while loop causes memory use to climb, and if monitored from PERFMON, this indicates a memory leak.

CAUSE
The CDataSource::OpenFromFileName function, in the ATL source code, calls IDataInitialize::LoadStringFromStorage, which in turn calls OLEDB32 LoadStringFromStorage. Inside the function call of LoadStringFromStorage, the initialization string is created and populated with the content of the .udl file. The CoTaskMemAlloc function is called to allocate memory for this string and the ATL OLE DB consumer caller gets the string back.

It is the caller's responsibility to free the memory allocated for the init string.

After returning from LoadStringFromStorage, CDataSource::OpenFromFileName calls into CDataSource::OpenFromInitializationString which takes the init string and makes the connection, the following code illustrates this point:

hr = spDataInit->GetDataSource(NULL, CLSCTX_INPROC_SERVER, szInitializationString,  IID_IDBInitialize, (IUnknown**)&m_spInit); However, after the connection is made, the OpenFromFileName function doesn't make the call to free the memory allocated to the initialization string, and that is the cause of the memory leak.

RESOLUTION
A workaround is to modify OpenFromFileName in the ATLDBCLI.h file to free the allocated memory at the the end of the function. The following code illustrates this workaround:

HRESULT OpenFromFileName(LPCOLESTR szFileName) {   CComPtr spDataInit; LPOLESTR                szInitString;

HRESULT hr = CoCreateInstance(CLSID_MSDAINITIALIZE, NULL, CLSCTX_INPROC_SERVER,IID_IDataInitialize, (void**)&spDataInit); if (FAILED(hr)) return hr;

hr = spDataInit->LoadStringFromStorage(szFileName,&szInitString); if (FAILED(hr)) return hr;

hr = OpenFromInitializationString(szInitString); if (FAILED(hr)) return hr;

//Done with the szInitString so free the string here. if(szInitString) CoTaskMemFree((void*)szInitString);

return hr; } Notes


 * 1) ATLDBCLI.h is the main file that contains the implementation of ATL OLE DB consumer template classes. It is best to make a copy of this header file to your local project directory, and modify it directly there.
 * 2) To use it in your project, you may want to employ #include "Atldbcli.h".
 * 3) Set a break point in the revised OpenFromFileName function and debug into it, so you can make sure you use the revised header file.

STATUS
Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article.

Steps to Reproduce Behavior
  Create a .udl file. Use the following two articles that delineate steps to create .udl files.

"Q244659 HOWTO: Create a Data Link File with Windows 2000" "Q195913 UDL Datalinks on Windows NT" Copy and then paste the following code into the .cpp file, modify the name of .UDL file and build it as console project.  Execute it and start PERFMON. The private bytes of the running process increase over time. #include "atldbcli.h" void main {   CoInitialize(NULL); while(true){ CDataSource db; HRESULT hr;

hr = db.OpenFromFileName(L"connection1.udl"); if( hr != S_OK ) MessageBox(0,"Failure","",1); db.Close; }   CoUninitialize; } 

Additional query words:

Keywords : kbATL kbDatabase kbDTL kbVC600bug kbConsumer

Version : WINDOWS:3.0

Platform : WINDOWS

Issue type : kbbug

Technology : kbvcSearch