C++ Builder IDE >> ADO Memory Leak - Somewhat inexperienced

by Steven Brown » Sat, 03 Sep 2005 02:53:28 GMT


I am somewhat new to ADO.
I am trying to resolve a slight memory leak in ADO using the CreateParameter call. It seems to manifest itself when I use an adVarChar as the type. When I comment out the 2nd CreateParameter call the Leak seems to disappear. I not sure if I am creating and destroying these objects properly. Could some one let me know. The following is a snip it of my code.


BSTR bstrCom = SysAllocString(WideString("_hdmSingletonHDMM"));
BSTR bstrTableNo = SysAllocString(WideString("TableNoField"));
BSTR bstrDVValue = SysAllocString(WideString("TableNoField"));
BSTR bstrDVValue2 = SysAllocString(WideString(""));

if (!cmd) {
if (SUCCEEDED (hr))
hr = CoCreateInstance(CLSID_CADOCommand, NULL,
CLSCTX_INPROC_SERVER,
IID_IADOCommand, (LPVOID *) &cmd);
If (SUCCEEDED(hr))
hr = cmd->putref_ActiveConnection(conn);

if(SUCCEEDED(hr)) {
hr = cmd->put_CommandText(bstrCom);
hr = cmd->put_CommandType(adCmdStoredProc);
}

int iFieldSize = 2;
hr = cmd->CreateParameter(bstrTableNo/*Param1*/,
adSmallInt, adParamInput, iFieldSize,
Variant(2),&ppiPrm);
ADOParameters *Prms = 0;
cmd->get_Parameters(&Prms);
Prms->Append(ppiPrm);
//Set up Parameter one - This seems to be the cause
iFieldSize = 40;
hr = cmd->CreateParameter(/*Param1*/bstrDVValue, adVarChar,
adParamInput, iFieldSize, Variant(bstrDVValue2), &ppiPrm2);
Prms->Append(ppiPrm2);
.
.
.

The following is how I cleanup

if (ppiPrm2) {
ppiPrm2->Release();
}
if (ppiPrm) {
ppiPrm->Release();
}
if (Prms)
Prms->Release();
SysFreeString(bstrCommand);
SysFreeString(bstrTableNoField);
SysFreeString(bstrMrNum);
if (cmd) {
cmd->Release();
cmd = 0;
}


I hope that I do not have too many issues with this code. I do not have a real clear understanding on how to free up memory with Com objects. I had an earlier Post on AUG 19th. The suggestions there got me steered in the right direction.
Any additional suggestions are much appreciated



C++ Builder IDE >> ADO Memory Leak - Somewhat inexperienced

by Vladimir Stefanovic » Sat, 03 Sep 2005 18:22:32 GMT


Go to aso group, and find the thread:

Problem on memory leak with TADOQuery

25. jul 2005 13:48

... you may be interested in it.




--
Best regards,
Vladimir Stefanovic







C++ Builder IDE >> ADO Memory Leak - Somewhat inexperienced

by Vladimir Stefanovic » Sat, 03 Sep 2005 18:23:06 GMT

aso should be ADO group ;)


--
Best regards,
Vladimir Stefanovic








ADO Memory Leak - Somewhat inexperienced

by Steven Brown » Wed, 07 Sep 2005 00:18:43 GMT

Thanks for responding Vladimr
I have checked out TADOQuery posting and have similar experience working with the Variants I have found

If I set a parameter like this: ADOCheck(ppiPrm2->put_Value(Variant(WideString(sCmd)))); sCmd would never get freed. So I manage it . Allocating with SysAllocString and Free it using SysFreeString. This has cleared that problem up. But the hr = cmd->CreateParameter(bstrTableNo/*Param1*/,
adSmallInt, adParamInput, iFieldSize,
Variant(2),&ppiPrm); as described above I feel helpless in trying to solve the memory leak it causes.

I have a similar problem with the Execute statement The memory leaks are small but they eventually grow an cause problems over time.

VARIANT vtEmpty;
VARIANT vtEmpty2;

vtEmpty.vt = VT_ERROR;
vtEmpty.scode = DISP_E_PARAMNOTFOUND;
vtEmpty2.vt = VT_ERROR;
vtEmpty2.scode = DISP_E_PARAMNOTFOUND;
rs = NULL;
ADOCheck(cmd2->Execute( &vtEmpty, &vtEmpty2, adCmdStoredProc | adExecuteNoRecords, &rs));
cmd2->Release();
cmd2 = 0;

It is difficult to solve these issues on my own. I asking for anymore suggestions or approaches to solve theses issues.

Thanks for your Attention to this dilemma.
"Vladimir Stefanovic" < XXXX@XXXXX.COM > wrote:



Similar Threads

1. Memory leak or no memory leak..

Hi,

 I've big problem with memory use of my application. FastMM or
AQTime's (trial version, if that matters) memory profiler doesn't find
any leaks. AQTime finds with resource profiler about 10 "Task memory"
leaks when GUIDToStr is called, but I think those are not real leaks.

 However memory usage grows steadily. FastMMUsageTracker shows new
memory blocks added as "allocated" or "reserved" for system. Task
manager also displays steady rise in memory usage (about 4 kb / s).

 The application uses COM to communicate with an OPC Server. There are
a lot of variants used in interfaces, and it looks like the problem is
present only when string or array of byte -data is transferred.

 Any ideas how to debug this?

2. ADO Memory Leak issue

3. ado memory leak? - source provided

I'm trying to find a memory leak in my code that uses ADO and have a sample 
that exhibits the leak. I started with some sample code from Matt Neerincx 
(thank you) and modified it to resemble the way it is executed in my program 
and a COM 
component. 

The test includes a loop which: 
1. connects to the database (jet) 
2. executes a command to delete records from a table 
3. executes a command (3 times) to add a record to the table 
4. disconnects 

I've constructed the test using commands in stored procedures, and using 
commands as text with and without parameters. Compiling each way results in 
the leak. The code is below. Can anyone 
point out the leak? 

Thanks. 


#include "stdafx.h" 
#include <atlbase.h> 
//#include "Test2.h" 
#include "conio.h" 

#pragma warning( push ) 
#pragma warning( disable : 4146 ) 
#import "c:\Program Files\Common Files\system\ado\msadox.dll" 
#import "c:\Program Files\Common Files\system\ado\msado15.dll" 
rename("EOF","EndOfFile") 
#pragma warning( pop ) 

#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 

//#define USE_CMDPROC 
//#define USE_PARAMS 

void RunSample(); 
ADODB::_ConnectionPtr GetJetConnection(); 
void RunSingleLoop(); 
void Reset(ADODB::_ConnectionPtr conn); 
void AddRecords(ADODB::_ConnectionPtr conn); 

///////////////////////////////////////////////////////////////////////////// 
// The one and only application object 

CWinApp theApp; 

using namespace std; 

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) 
{ 
int nRetCode = 0; 

// initialize MFC and print and error on failure 
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) 
{ 
// TODO: change error code to suit your needs 
cerr << _T("Fatal Error: MFC initialization failed") << endl; 
return -1; 
} 

CoInitialize(NULL); 
RunSample(); 
CoUninitialize(); 

return nRetCode; 
} 

#define LOOP_COUNT 100000 // Number of loops to execute. 

void RunSample() 
{ 

#if defined(USE_CMDPROC) && defined(USE_PARAMS) 
#error ("Invalid configuration") 
#endif 

ADODB::_ConnectionPtr global_conn = NULL; 
int i; 

try 
{ 
// Open global conn to keep Jet loaded (perf). 
global_conn = GetJetConnection(); 

try 
{ 
global_conn->Execute(L"drop table 
T1",NULL,ADODB::adExecuteNoRecords|ADODB::adCmdText); 
} 
catch ( _com_error ex ) 
{ 

} 

global_conn->Execute(L"create table T1(f1 int, f2 
int)",NULL,ADODB::adExecuteNoRecords|ADODB::adCmdText); 

for (i=1; i<=LOOP_COUNT; i++ ) 
{ 
RunSingleLoop(); 

Sleep(5); 
if ( 0 == (i%1000)) 
{ 
printf( "Completed %08lu of %08lu iterations.\n", i, LOOP_COUNT ); 
while ( _kbhit() ) 
{ 
int x = _getch(); 
if ( 'Q' == x || 'q' == x ) 
{ 
return; 
} 
} 
} 
} 
} 

catch( _com_error ex ) 
{ 
// Robust error trapping left as an exercise for the reader. (G) 
ASSERT(FALSE); 
} 

return; 
} 

_bstr_t JET_CONNECT(L"Provider=Microsoft.Jet.OLEDB.4.0;Data 
Source=C:\\NW99.mdb;"); 

ADODB::_ConnectionPtr GetJetConnection() 
{ 
HRESULT hr; 
ADODB::_ConnectionPtr conn = NULL; 

hr = conn.CreateInstance( __uuidof(ADODB::Connection) ); 
//if ( FAILED( hr ) ) throw( _com_error( hr, NULL ) ); 

conn->CursorLocation = ADODB::adUseServer; 

// Open connection. 
conn->Open( JET_CONNECT, "", "", -1L ); 
//Setting this property doesn't help. 
//conn->Properties->Item["Jet OLEDB:Max Buffer Size"]->Value = 500L; 

return conn; 
} 

void RunSingleLoop() 
{ 
ADODB::_ConnectionPtr conn = NULL; 

// Open local conn for loop. 
conn = GetJetConnection(); 

Reset(conn); 

// The AddRecords generate the memory leaks 
AddRecords(conn); 
AddRecords(conn); 
AddRecords(conn); 

conn->Close(); 
conn = NULL; 
} 

void Reset(ADODB::_ConnectionPtr conn) 
{ 
ADODB::_CommandPtr cmd = NULL; 
CComVariant v1; 

HRESULT hr = cmd.CreateInstance( __uuidof(ADODB::Command) ); 

/* 
Query: qdMissingData 

PARAMETERS P1 Long; 
DELETE * FROM T1 WHERE f1=P1; 
*/ 

cmd->ActiveConnection = conn; 
#ifdef USE_CMDPROC 
cmd->CommandText = L"qdMissingData"; 
cmd->CommandType = ADODB::adCmdStoredProc; 
#else 
#ifdef USE_PARAMS 
cmd->CommandText = L"DELETE * FROM T1 WHERE f1=?"; 
#else 
cmd->CommandText = L"DELETE * FROM T1 WHERE f1=1"; 
#endif 
cmd->CommandType = ADODB::adCmdText; 
#endif 

#ifdef USE_PARAMS 
v1 = 1L; 
cmd->Parameters->Append(cmd->CreateParameter( 
L"P1",ADODB::adInteger,ADODB::adParamInput,-1, v1)); 
v1.Clear(); 
#endif 

cmd->Execute(NULL,NULL,ADODB::adExecuteNoRecords); 

cmd->ActiveConnection = NULL; 
cmd = NULL; 
} 

void AddRecords(ADODB::_ConnectionPtr conn) 
{ 
ADODB::_CommandPtr cmd = NULL; 
CComVariant v1; 
CComVariant v2; 
static long lCounter = 1; 

// Now create parameterized ADO call. 
HRESULT hr = cmd.CreateInstance( __uuidof(ADODB::Command) ); 
// if ( FAILED( hr ) ) throw( _com_error( hr, NULL ) ); 

cmd->ActiveConnection = conn; 

/* 
Query: qiMissingRecord: 

PARAMETERS P1 Long, P2 DateTime; 
INSERT INTO T1 ( f1, f2 ) VALUES (P1, P2); 
*/ 

// Create insert statement and setup params. 
#ifdef USE_CMDPROC 
cmd->CommandText = L"qiMissingRecord"; 
cmd->CommandType = ADODB::adCmdStoredProc; 
#else 
#ifdef USE_PARAMS 
cmd->CommandText = L"INSERT INTO T1 ( f1, f2 ) VALUES (?, ?)"; 
#else 
cmd->CommandText = L"INSERT INTO T1 ( f1, f2 ) VALUES (1, 2)"; 
#endif 
cmd->CommandType = ADODB::adCmdText; 
#endif 

#ifdef USE_PARAMS 
v1 = 1L; 
v2 = lCounter++; 
cmd->Parameters->Append(cmd->CreateParameter( 
L"P1",ADODB::adInteger,ADODB::adParamInput,-1, v1)); 
cmd->Parameters->Append(cmd->CreateParameter( 
L"P2",ADODB::adInteger,ADODB::adParamInput,-1, v2)); 
v1.Clear(); 
v2.Clear(); 
#endif 

// Execute statement. 
cmd->Execute(NULL,NULL,ADODB::adExecuteNoRecords); 

// Cleanup 
cmd->ActiveConnection = NULL; 
cmd = NULL; 
} 

4. Memory leaks in ADO calls

5. How to detect memory leak and detect who causes a memory leak

6. ADO - permanent memory leak?!

7. Process Memory Leak? Delphi+MySql+ADO+MyOdbc

I've got some problems:

While using Mysql 4.0.20a for windows+MyODBC 3.51.07+Both delphi 6 or 
delphi 7.

While testing for a MyODBC memory leak (present in myodbc before 
3.51.07) I had this strange (for me) behaviour. The Heap it's apparently 
perfect, BUT the Process Memory grows quite fast. As indicated by Task 
Manager and the included function.

I've tried with different components, both MySQLDAC e Zeoslib gives no 
sign of this .. but I've got the same problem in another apps with 
ZeosLib (Still trying to reproduce the problem in a small example).

  I've tested it all with memcheck. No heap leak.

Any idea?

I'll post the leakt.zip attachment on borland.public.attachment (Hoping 
it's correct, sorry for any mistake.. :-( ).

Marco Banfi.


The "core" is:

   for i:=0 to 10000 do begin
     if StopMeCB.Checked then
     begin
         StopMeCB.Checked:=false;
         Exit;
     end;

     ADOQuery := TADOQuery.Create(nil);
     ADOQuery.ConnectionString := optConnString;
     ADOQuery.CursorLocation := clUseClient; //No change..
     ADOQuery.SQL.TEXT := 'SELECT * FROM log_option';
     ADOQuery.Active := True;

     FreeAndNil( ADOQuery);

     iter:=i;
     PsMemoryButtonClick(Sender);
     Application.ProcessMessages;

   end;

8. Memory leak with ADO