• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 969
  • Last Modified:

C++ ADO Command Memory Leak

There appears to be a memory leak in my C++ dll caused by ADO.
My code can open a connection and read data from my SQL server without any leaks. But when I try to write data back to the database it creates a memory leak.

I have used Perfmon to confirm this. The Private Bytes counter increases linearly with time with each iteration of the run.

Here is my initial method:

------------------------------
PointCollectionCls* PointStartup::GeneratePoints(bool useDBase, char PeakTrough, PriceDataCls * PriceData)
{
      PointCollectionCls * PointCollection = new PointCollectionCls(int(PriceData->LatestTick/2));
      bool dataFound=true;
      CString sqlText;
      _variant_t recordsAffected(0L);
      HRESULT hr;
      int nearestLatestTick=1;

      if (useDBase)
      {
            //Search DBase for relevant data
            CnnPtr oCn;
            RecPtr oRecSet;
            RecPtr oRecSet2;
            
            _variant_t vNull;
            vNull.vt = VT_ERROR;
            vNull.scode = DISP_E_PARAMNOTFOUND;

            try
            {
                  oCn.CreateInstance( __uuidof( Connection ) );
                  oRecSet.CreateInstance( __uuidof( Recordset ) );

                  //CString connString = "Driver={SQL Server};Server=" + GetSQLServerName() + ";Trusted_Connection=no;Database=
                  CString connString = "Provider=sqloledb;Data Source=" + GetSQLServerName() + ";Initial Catalog=CPSystem;Uid=sa;Pwd=password;";
                  oCn->CommandTimeout = 240;
                  oCn->Open(connString.AllocSysString(),"sa","password",NULL);
                  sqlText = "EXEC [CP_GetPoints] " + ConvToStr(PriceData->LatestTick) + ", '" + ConvToStr(PriceData->symbol) + "', '" + ConvToStr(PeakTrough) + "'";
                  oRecSet->PutRefActiveConnection(oCn.GetInterfacePtr());
                  hr = oRecSet->Open(_variant_t(sqlText.AllocSysString()), vNull, adOpenForwardOnly, adLockReadOnly, adCmdText);
                  
                  
                  if (oRecSet->GetadoEOF())
                  {
                        dataFound=false;
                  }

                  if (dataFound)
                  {
                        LoadDataFromDBase(*PointCollection, oRecSet);
                  }
                  else
                  {
                        ///*
                        //Check whether previous day's points exist and just update
                        dataFound=true;
                        oRecSet2.CreateInstance( __uuidof( Recordset ) );
                        oRecSet2->PutRefActiveConnection(oCn.GetInterfacePtr());
                        sqlText = "EXEC [CP_GetClosestTickPoints] " +  ConvToStr(PriceData->LatestTick) + ", '" + ConvToStr(PriceData->symbol) + "', '" + ConvToStr(PeakTrough) + "'";
                        hr = oRecSet2->Open(_variant_t(sqlText.AllocSysString()), vNull, adOpenForwardOnly, adLockReadOnly, adCmdText);
                        
                        if (oRecSet2->GetadoEOF())
                        {
                              dataFound=false;
                        }
                        if (dataFound)
                        {
                              nearestLatestTick = oRecSet2->Fields->GetItem("LatestTick")->GetValue().intVal;
                              LoadDataFromDBase(*PointCollection, oRecSet2);
                        }
                        
                        //Save data to DBase
                        SaveDataToDBase(*PointCollection, oCn, *PriceData);
                        
                        oRecSet2->Close();
                        //*/
                  }
                  
                  oRecSet->Close();
                  oCn->Close();
            }
            catch ( _com_error &e)
            {
                  AfxMessageBox(e.Description(), NULL,NULL);
                  delete PointCollection;
                  PointCollection = NULL;
            }
      }
      else
      {
            CreateNewPointCollection(PriceData, PointCollection, PeakTrough);
            //PointFinderCls generates points in ascending order (earliest first, latest last)

      }
      return PointCollection;
}
----------------------------------

Note:
1. useDBase is always set to true
2. the PointCollection object gets deleted in the external parent calling method, so this is not the problem.
3. the external calling method makes multplie calls (1000s of iterations) to GeneratePoints().

The problem is in the SaveDataToDBase() method:

-------------------------
void PointStartup::SaveDataToDBase(PointCollectionCls &PointCollection, CnnPtr &oCn, PriceDataCls &PriceData)
{
      int n;
      CString sqlText;
      short peakVal;
      _CommandPtr oCommand;
      oCommand.CreateInstance( __uuidof( Command ));
      oCommand->ActiveConnection = oCn;
      oCommand->CommandType = adCmdText;
      _variant_t vNull;
      vNull.vt = VT_ERROR;
      vNull.scode = DISP_E_PARAMNOTFOUND;
      sqlText = "";

      for (n=0; n < PointCollection.count; n++)
      {
            if (PointCollection[n].peak) peakVal=1;
            else peakVal=0;
            
            sqlText += "EXEC [CP_InsertPoints] '" + CString(PriceData.symbol) + "', ";
            sqlText += ConvToStr(PointCollection[n].time) + ", " + ConvToStr(PointCollection[n].price) + ", ";
            sqlText += ConvToStr(PointCollection[n].timeEarliestBar) + ", " + ConvToStr(PointCollection[n].timeLatestBar) + ", ";
            sqlText += ConvToStr(PriceData.EarliestTick) + ", " + ConvToStr(PriceData.LatestTick) + ", ";
            sqlText += ConvToStr(peakVal) + ", " +  ConvToStr(PointCollection[n].pointHeight) + ", ";
            sqlText += ConvToStr(PointCollection[n].pointTotalVolume) + ", " +  ConvToStr(PointCollection[n].pointBelowVolume) + ", ";
            sqlText += ConvToStr(PointCollection[n].invPointBelowVolumeLeft) + ", " +  ConvToStr(PointCollection[n].invPointBelowVolumeRight) + ", ";  
            sqlText += ConvToStr(PointCollection[n].avgBarLength) + ", ";
            sqlText += ConvToStr(PointCollection[n].barVolatility) + ", " +  ConvToStr(PointCollection[n].interBarVolatility) + ", ";  
            sqlText += ConvToStr(PointCollection[n].pointSig) + ", " +  ConvToStr(PointCollection[n].stillOpen);
            sqlText += '\n';
      }
      oCommand->CommandText = sqlText.AllocSysString();
      oCommand->Execute(&vNull, &vNull, adExecuteNoRecords);
      oCommand->ActiveConnection = NULL;
}
----------------------------------

Now when I comment out the line:
"oCommand->Execute(&vNull, &vNull, adExecuteNoRecords);"
the memory leak disappers completely!

How can I possibly resolve this?
0
cpeters1
Asked:
cpeters1
  • 2
  • 2
1 Solution
 
prosh0tCommented:
it seems like oCommand->CommandText = sqlText.AllocSysString(); would be causing the problem... I have no idea why it would go away when you comment out the execute command.  Maybe hte compiler knows it doesn't need the previous line and so it discards it.. who knows.

Anyways, try deleting the oCommand->CommandText, and the oCommand object itself.  The rule is, ANYTHIGN that is allocated must be deallocated.


delete oCommand->CommandText;
delete oCommand;

0
 
cpeters1Author Commented:
oCommand is a smart pointer so I cannot "delete" oCommand.
oCommand->CommandText is not a pointer either.

See I've also used oCn->Execute(sqlText.AllocSysString(), NULL, adExecuteNoRecords);
instead of oCommand->Execute(...)
and this gives me the same memory leak.
0
 
mastooCommented:
You need to clean up your AllocSysString.  From help on that method...

Commonly, if this string is passed to a COM function as an [in] parameter, then this requires the caller to free the string. This can be done by using SysFreeString, as described in the Platform SDK. For more information, see Allocating and Releasing Memory for a BSTR.

Keep a reference to it, pass the reference into Execute, and clean up after the call.

0
 
cpeters1Author Commented:
mastoo you're a genius! The memory leak has completely gone!
I've spent over a week trying to solve this problem. Thanks very much! : )

0
 
mastooCommented:
:-)
0

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now