none
Tracking down a memory leak - cannot interpret a suspect call stack flagged by Microsoft DebugDiag Memory Pressure Analysis feature RRS feed

  • Question

  • I am trying to track down a memory leak using DebugDiag's Memory Pressure Analysis feature and am having difficulty interpreting the suspect call stacks in the memory analysis report.  The problem at hand involves a program for which I reported previously a memory leak problem on this forum and which was resolved.  The new problem appears to be of a different source.

     The problem involved is a data acquisition program written in C# which makes calls to an interop COM dll to retrieve data from the outside world (data points from a programmable logic controller).  The COM dll itself is written in C++ and actually talks COM to the outside world (a Kepware OPC IO server).  In C++, once the COM dll has retrieved data from the outside world it conveys the data back to the C# client caller using IDispatch::Invoke.  I have shown the call stack below.  The last portion of application code is IOManager.IOOPCServer.WriteToDevice(IOManager.UpdatedIOPoint).  I have shown this code below well.  Within this code it is the call to IIOInterface.WriteAsync which is the call to the COM dll.  I have shown this code as well below.  

     

     At first I thought the memory leak problem may be inside WriteAsync, which uses VariantChangeType to convert incoming variants (already BSTR's) to local BSTR's, due to the fact that the code does in-place type changes (note that the first two arguments to VariantChangeType are the same variant pointer) but I suspect this was a red-herring and not actually a leak.   Reason for my initial suspicion was that I read on various forums, including I believe an Microsoft Tech Note that in-place variant type changes result in leaks (???), however, changing the code to avoid this in-place type change did not resolve the leak.  Also, the call stack flagged by DebugDiag does not even reference WriteAsync, further making me think the problem is elsewhere.  The calls in between CreateApplicationContext and DeactivateActivationContext I suspect are infrastructure, possibly marshaller?

     

     Any help in interpreting this call stack would be greatly appreciated.

     

     /// Flagged call stack from DebugDiag

     

                 Call stack sample 1

     

                      Address  0x07b4d268

                      Allocation Time  00:00:26 since tracking started

                      Allocation Size  1.52 KBytes

     

                      Function  Source  Destination

                      ntdll!RtlDeactivateActivationContext+ef   

                      ntdll!RtlAllocateHeap

                      ntdll!NtSetEventBoostPriority+c   

                      ntdll!RtlpUnWaitCriticalSection+22   

                      ntdll!NtSetEventBoostPriority

                      ntdll!RtlLockHeap+2b7    ntdll!RtlpUnWaitCriticalSection

                      ntdll!RtlDetermineDosPathNameType_U+742   

                      mscorwks!StrongNameErrorInfo+503a   

                      mscorwks!CreateApplicationContext+166d0   

                      IOManager.IOOPCServer.WriteToDevice(IOManager.UpdatedIOPoint) 

                      IOManager.IOOPCServer.WriteToDevice(IOManager.UpdatedIOPoint) 

                      IOManager.IOMMain.HandleSetOutputRequest(System.String,

                      System.String)   

                      IOManager.IOOPCServer.WriteToDevice(IOManager.UpdatedIOPoint)

                      IOManager.IOMService.SetOutput(System.String, System.String)  

                       IOManager.IOMMain.HandleSetOutputRequest(System.String,

                      System.String)

                      System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(System.Object,

                      System.Object[], System.Object[] ByRef)   

                      System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean)   

                      System.ServiceModel.Diagnostics.Utility+AsyncThunk.UnhandledExceptionFrame(System.IAsyncResult)

                        

                      System.ServiceModel.AsyncResult.Complete(Boolean)   

                      mscorwks!StrongNameErrorInfo+129a2   

                      System.ServiceModel.Diagnostics.Utility+AsyncThunk.UnhandledExceptionFrame(System.IAsyncResult)

                        

                      System.ServiceModel.AsyncResult.Complete(Boolean)   

                      mscorwks!DllUnregisterServerInternal+c46a   

                      System.ServiceModel.Diagnostics.Utility+IOCompletionThunk.UnhandledExceptionFrame(UInt32,

                      UInt32, System.Threading.NativeOverlapped*)   

                      System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32,

                      UInt32, System.Threading.NativeOverlapped*)   

                      mscorwks+1b4c   

                      mscorwks!CoUninitializeEE+4df3   

                      mscorwks+9cba   

                      mscorwks!CorExitProcess+2bcf   

                      mscorwks!CreateApplicationContext+bc35   

                      ntdll!bsearch+43   

                      ntdll!bsearch+43   

                      ntdll!bsearch+43   

                      ntdll!RtlFindCharInUnicodeString+147   

                      kernel32!GetModuleHandleW+4f   

                      kernel32!GetModuleHandleW+4f   

                      kernel32!GetModuleHandleW+1d9   

                      ntdll!KiUserApcDispatcher+25   

                      ntdll!ZwQueryVirtualMemory+c   

                      kernel32!VirtualQueryEx+1d    ntdll!ZwQueryVirtualMemory

                      ntdll!LdrInitializeThunk+24   

                      ntdll!ZwTestAlert+c   

                      ntdll!NtContinue+c   

                      ntdll!KiUserApcDispatcher+3a    ntdll!NtContinue

                      kernel32!GetModuleHandleA+df   

     

    /// C# method which calls COM

     

                public bool WriteToDevice(UpdatedIOPoint localUpdate)

                {

                      if (Properties.Settings.Default.Verbosity >= (int)VerboseSetting.Verbose_2)

                            Diagnostics.LogMethodCall(MethodBase.GetCurrentMethod(), new object[] { localUpdate.Address, localUpdate.NewValue });

     

                      bool ExceptionEncountered = false;

                      bool ReturnStatus = false;

     

                      try

                      {

                            uint ReturnValue;

     

                            if (IIOInterface != null)

                            {

                                  lock (IIOInterface)

                                  {

                                        // Based on the tests above, now that the current state of the I/O point

                                        // has been determined, we must now issue an update request to the

                                        // I/O Server so

                                        //

                                        object ServerName = Name;

                                        object ChannelName = localUpdate.ChannelName;

                                        object Address = localUpdate.Address;

                                        object NewValue = localUpdate.NewValue;

     

                                        try

                                        {

                                              IIOInterface.WriteAsync(out ReturnValue, ref ServerName,

                                                                                                           ref ChannelName,

                                                                                                           ref Address,

                                                                                                           ref NewValue);

                                              if (ReturnValue == 0)

                                              {

                                                    ReturnStatus = true;

                                              }

                                        }

                                        catch (Exception e)

                                        {

                                              ExceptionEncountered = true;

                                              if (Properties.Settings.Default.Verbosity >= (int)VerboseSetting.Verbose_1)

                                                    Log.Send("WriteToDevice() - Error: failed during WriteAsync() call for Server: " + Name +

                                                          " Channel: " + localUpdate.ChannelName + " Address: " + localUpdate.Address + " with Error: " + e.ToString(),

                                                          Log.Level.Error, Log.Destination.DiagnosticSystem);

                                        }

                                  }

                            }

                            else

                            {

                                  if (Properties.Settings.Default.Verbosity >= (int)VerboseSetting.Verbose_1)

                                        Log.Send("WriteToDevice() - Error: Interface object IIOInterface not established. Failed to issue command for Server: " +

                                              Name + " Channel: " + localUpdate.ChannelName + " Address: " + localUpdate.Address,

                                              Log.Level.Error, Log.Destination.Trace);

                            }

                            if (ExceptionEncountered == true)

                            {

                                  // we want to clear out the I/O Server with the channel.

                                  //

                                  DisconnectServer();

                            }

     

                            // We had an error in the attempt to issue the read or write to the Client DLL.

                            // Set the Channel to a false connection state and continue.

                            if (ReturnStatus == false)

                            {

                                  IOChannel LocalChannel = IOMMain.GetIOChannel(this, localUpdate.ChannelName);

                                  if (LocalChannel.IsConnected != false)

                                  {

                                        IOMMain.SetChannelConnectionStatus(this, LocalChannel, false);

     

                                        if (Properties.Settings.Default.Verbosity >= (int)VerboseSetting.Verbose_1)

                                              Log.Send("WriteToDevice() - Failed to write. Setting Channel " + localUpdate.ChannelName + " to NotConnected for Server: " +

                                                    Name + " for Address: " + localUpdate.Address,

                                                    Log.Level.Informational, Log.Destination.Trace);

                                  }

                            }

                      }

                      catch (Exception e)

                      {

                            Diagnostics.LogException(e);

                            Log.Send("WriteToDevice() Exception - " + e.ToString(), Log.Level.Error, Log.Destination.DiagnosticSystem);

                      }

     

                      Diagnostics.LogMethodResult(MethodBase.GetCurrentMethod(), ReturnStatus);

     

                      return ReturnStatus;

                }

     

    ///// Inside of COM

    STDMETHODIMP CIOPCClientInterface::WriteAsync(ULONG* ReturnValue, VARIANT* szServerName, VARIANT* szGroupName, VARIANT* szItemName, VARIANT* szValue)

    {

          AFX_MANAGE_STATE(AfxGetStaticModuleState());

     

          // TODO: Add your implementation code here

          HRESULT           hRes                          = S_OK;

          CFMCOPCServerInterface * pServer    = NULL;

          CFMCOPCGroupInterface * pGroup            = NULL;

     

          try

          {

                if (m_pFmcOPCClientInterface != NULL)

                {

                      VariantChangeType(szServerName, szServerName, 0, VT_BSTR);

                      CString ServerName(szServerName->bstrVal);

     

                      VariantChangeType(szGroupName, szGroupName, 0, VT_BSTR);

                      CString GroupName(szGroupName->bstrVal);

     

                      VariantChangeType(szItemName, szItemName, 0, VT_BSTR);

                      CString ItemName(szItemName->bstrVal);

     

                      VariantChangeType(szValue, szValue, 0, VT_BSTR);

                      CString Value(szValue->bstrVal);

     

                      pServer = m_pFmcOPCClientInterface->Servers.GetAt(ServerName);

                      if (pServer)

                      {

                            pGroup      = pServer->Groups.GetAt(GroupName);

                      }

                      else

                      {

                            m_pFmcOPCClientInterface->LogException("CIOPCClientInterface", "WriteAsync", "Could not locate Server (" + ServerName + ") to initate a Write() call", E_FAIL);

                            return E_FAIL;

                      }

                      if (!pGroup)

                      {

                            m_pFmcOPCClientInterface->LogException("CIOPCClientInterface", "WriteAsync", "Could not locate Group (" + GroupName + ") to initate a Write() call", E_FAIL);

                            return E_FAIL;

                      }

                      CFMCOPCItemInterface * pItem = pGroup->m_arrItems[ItemName];

                      if (pItem)

                      {

                            hRes = pGroup->WriteAsync(pItem, *szValue);

                      }

                }

          }

          catch(CException* pException)

          {

                if (m_pFmcOPCClientInterface != NULL)

                {

                      char * szErrorMsg[MAX_PATH];

                      pException->GetErrorMessage((char *) szErrorMsg, MAX_PATH);

                      hRes = HRESULT_FROM_WIN32(GetLastError());

                      m_pFmcOPCClientInterface->LogException("CIOPCClientInterface", "WriteAsync", (char *)szErrorMsg, hRes);

                      pException->Delete();

                }

                hRes = E_FAIL;

          }

          *ReturnValue = hRes;

          return hRes;

    }

     

    • Moved by Leo Liu - MSFT Monday, September 12, 2011 6:01 AM Moved for better support. (From:Visual C# General)
    Thursday, September 8, 2011 3:07 PM

Answers

All replies