Link to home
Start Free TrialLog in
Avatar of kamaldev k r
kamaldev k rFlag for India

asked on

ADODB Command memory leak on execute()

I am getting memory leak on line paramcmd->Execute(NULL, NULL, NULL);. Just commenting the line give no leak. Any further resource need to free on invoking execute(). SQL server 2017



HRESULT CEpks870psDB::ReadPointParameters(const std::vector<std::wstring>& PointNames, std::vector<int>& ParamIds, const std::vector<std::wstring>& ParamNames, std::vector<db_param>& param_details)
{
   DWORD start_time = GetTickCount();
   log(L_PARAM, "%s: enter", __FUNCTION__);
   param_details.resize(PointNames.size());

   _CommandPtr paramcmd;
   paramcmd.CreateInstance(__uuidof(Command));
   paramcmd->ActiveConnection = m_pADOConnection;
   paramcmd->CommandType = adCmdText;
   paramcmd->Prepared = true;
   paramcmd->CommandTimeout = 30;

   // should return the same result as V_PointAttribute view in SQL.
   paramcmd->CommandText = L"SELECT TOP 1 AttributeIGDAAccess,IsStrValue,IsNumValue,IsIntValue, "
      L"ISNULL(StrValue,DefaultStrValue) AS StrValue,ISNULL(NumValue, DefaultNumValue) AS NumValue,ISNULL(IntValue, DefaultIntValue) AS IntValue, "
      L"AttributeDataSource,AttributeDataSourceAttribute, "
      L"MinNumValue,MaxNumValue,AttributeICONFIGAccess,a.AttributeName,p.PointDefinitionTypeID,a.AttributeDataType,a.AttributeDataType_2 "
      L"FROM Point p INNER JOIN PointTypeAttribute pta ON "
      L"p.PointID=? AND pta.AttributeID=? AND p.PointDefinitionTypeID=pta.PointDefinitionTypeID "
      L"LEFT OUTER JOIN PointAttribute pa ON "
      L"p.PointID=pa.PointID AND pta.AttributeID=pa.AttributeID "
      L"INNER JOIN Attribute a "
      L"ON pta.AttributeID=a.AttributeID";

   _ParameterPtr pcpointid = paramcmd->CreateParameter(L"PointID", adInteger, adParamInput, 0, _variant_t(1));
   paramcmd->Parameters->Append(pcpointid);
   _ParameterPtr pcparamname = paramcmd->CreateParameter(L"ParamID", adInteger, adParamInput, 0, _variant_t(1));
   paramcmd->Parameters->Append(pcparamname);

   for (int i = 0; i < PointNames.size(); i++)
   {
      int pointid = 0;
      int createtime = 0;

      GetPointId(PointNames[i], pointid, createtime);

      param_details[i].point_createtime = createtime;

      if (pointid == 0)
      {
         param_details[i].Default.vt = VT_ERROR;
         param_details[i].Default.scode == M4_INV_POINT;
         continue;
      }

      param_details[i].Default.vt = VT_ERROR;
      param_details[i].Default.scode = M4_INV_PARAMETER;

      int paramid = 0;
      if (ParamIds.size()) paramid = ParamIds[i];

      if (paramid == 0)
      {
         paramid=GetParameterID(ParamNames[i]);
      }

      if (paramid == 0)
      {
         continue;
      }

      paramcmd->Parameters->Item[L"PointID"]->Value = pointid;
      paramcmd->Parameters->Item[L"ParamID"]->Value = paramid;

      try
      {
         if (m_pADORecordSet->State == adStateOpen)
            m_pADORecordSet->Close();

         m_pADORecordSet = paramcmd->Execute(NULL, NULL, NULL);

         if (m_pADORecordSet->State == adStateOpen &&
            !(m_pADORecordSet->BOF) &&
            !(m_pADORecordSet->adoEOF))
         {
            param_details[i].sIGDAAccess = m_pADORecordSet->Fields->GetItem(short(0))->Value;
            param_details[i].sSourceSystem = m_pADORecordSet->Fields->GetItem(short(7))->Value;
            param_details[i].sSourceAtt = m_pADORecordSet->Fields->GetItem(short(8))->Value;

            const bool isstr = m_pADORecordSet->Fields->GetItem(short(1))->Value.intVal != 0;
            const bool isnum = m_pADORecordSet->Fields->GetItem(short(2))->Value.intVal != 0;
            const bool isint = m_pADORecordSet->Fields->GetItem(short(3))->Value.intVal != 0;

            _variant_t val;
            if (isstr)
            {
               val = m_pADORecordSet->Fields->GetItem(short(4))->Value;
            }
            else if (isnum)
            {
               val = m_pADORecordSet->Fields->GetItem(short(5))->Value;
            }
            else if (isint)
            {
               val = m_pADORecordSet->Fields->GetItem(short(6))->Value;
            }

            _variant_t vDTValue = m_pADORecordSet->Fields->GetItem(short(14))->Value;
            _variant_t vDT2Value = m_pADORecordSet->Fields->GetItem(short(15))->Value;

            VariantValueCopy(&param_details[i].Default, val, vDTValue, vDT2Value);

            if (val.vt == VT_ERROR)
            {
               // VariantValueCopy checks vDT2Value to see if val.vt can be converted to GDAITEM.
               // If it fails here then should check VariantValueCopy, SQL db and the conversion code to GDAITEM.
               log(L_ERROR, "%s: pnt=%d prm=%d fail to convert err=%x", __FUNCTION__, pointid, paramid, val.scode);
            }

            param_details[i].vMinValue = m_pADORecordSet->Fields->GetItem(short(9))->Value;
            if (param_details[i].vMinValue.vt != VT_NULL)
            {
               param_details[i].vMinValue.ChangeType(VT_R4);
            }

            param_details[i].vMaxValue = m_pADORecordSet->Fields->GetItem(short(10))->Value;
            if (param_details[i].vMaxValue.vt != VT_NULL)
            {
               param_details[i].vMaxValue.ChangeType(VT_R4);
            }

            param_details[i].sICONFIGAccess = m_pADORecordSet->Fields->GetItem(short(11))->Value;
            param_details[i].AttributeName= _bstr_t(m_pADORecordSet->Fields->GetItem(short(12))->Value);
            param_details[i].lOrdinal= m_pADORecordSet->Fields->GetItem(short(13))->Value;

            dbcache::param.add(param_details[i].AttributeName, 0, paramid);
            m_pADORecordSet->Close();
         }
         else
         {            
            param_details[i].AttributeName = CA2W(dbcache::param.get_name(paramid).c_str());
         }
      }
      catch (_com_error &e)
      {
         log(L_LOG, "%s: exception caught %S", __FUNCTION__, e.ErrorMessage());
      }
   }
   paramcmd->ActiveConnection = NULL;
   paramcmd = NULL;
   DWORD took = GetTickCount() - start_time;
   log(L_LOG, "%s: exit count=%d took=%dms", __FUNCTION__, PointNames.size(), took);
   return S_OK;
}
Avatar of kamaldev k r
kamaldev k r
Flag of India image

ASKER

Adding the UMDH log details of memory leak.
   ntdll!RtlValidateProcessHeaps+249
   ntdll!LdrSetAppCompatDllRedirectionCallback+F52D
   ntdll!RtlAllocateHeap+32
   combase!PropVariantCopy+566
   OLEAUT32!SysFreeString+7F
   OLEAUT32!SysAllocStringLen+40
   msado15!???+0 : 6AF3DC9C
   msado15!???+0 : 6AF3E04E
   msado15!???+0 : 6AF38C12
   msado15!DllUnregisterServer+ED29
   msado15!DllUnregisterServer+32E69
........................................................
Avatar of ste5an
First of all, use the [code][/code] tags (or the </> button in the toolbar) to embed your code. Edit your post.

Well, I doubt it is the Execute() itself. Do you close all references?

if (m_pADORecordSet->State == adStateOpen)
    m_pADORecordSet->Close();

m_pADORecordSet = paramcmd->Execute(NULL, NULL, NULL);
if (m_pADORecordSet->State == adStateOpen &&
    !(m_pADORecordSet->BOF) &&
    !(m_pADORecordSet->adoEOF))
{
    // ..
    m_pADORecordSet->Close();
}
else
{
    param_details[i].AttributeName = CA2W(dbcache::param.get_name(paramid).c_str());
}

Open in new window

The problem is that you don't close it in all cases.. the above should imho read:

if (m_pADORecordSet->State == adStateOpen)
    m_pADORecordSet->Close();

m_pADORecordSet = paramcmd->Execute(NULL, NULL, NULL);
if (m_pADORecordSet->State == adStateOpen)
{
    if (!(m_pADORecordSet->BOF) &&  !(m_pADORecordSet->adoEOF))
    {
        // ..
    }
     else
    {
        param_details[i].AttributeName = CA2W(dbcache::param.get_name(paramid).c_str());
    }

    m_pADORecordSet->Close();
}

Open in new window

get updates from MSFT- to fix lit.  BTW: why do you think you have memory leak?

This question needs an answer!
Become an EE member today
7 DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform.
View membership options
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.