Re: ADODB Command memory leak



Matt,

I started with your code and modified it to (somewhat) closely represent
what I'm doing, and was able to re-produce the leak. Can you see where the
problem is?

My data access code is in a COM component, so I broke it out into functions
in this test program. There are two simple queries used, and they're
included in the comments. I just noticed that one of the queries actually
expects a parameter as a DateTime type, and this test program is passing it a
long - seems to work though.

Thanks,
Ken

// Test2.cpp : Defines the entry point for the console application.
//

#include "stdafx.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

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()
{
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(0);
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 );

return conn;
}

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

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

Reset(conn);
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;
cmd->CommandText = L"qdMissingData";
cmd->CommandType = ADODB::adCmdStoredProc;

v1 = 1L;

cmd->Parameters->Append(cmd->CreateParameter(
L"P1",ADODB::adInteger,ADODB::adParamInput,-1, v1));

v1.Clear();

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.
cmd->CommandText = L"qiMissingRecord";
cmd->CommandType = ADODB::adCmdStoredProc;

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();

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

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


.