Memory Leak when using DirectorySearcher.FindAll()

前端 未结 5 1545
孤街浪徒
孤街浪徒 2020-12-05 13:46

I have a long running process that needs to do a lot of queries on Active Directory quite often. For this purpose I have been using the System.DirectoryServices namespace, u

5条回答
  •  我在风中等你
    2020-12-05 14:23

    As strange as it may be, it seems that the memory leak only occurs if you don't do anything with the search results. Modifying the code in the question as follows does not leak any memory:

    using (var src = mySearcher.FindAll())
    {
       var enumerator = src.GetEnumerator();
       enumerator.MoveNext();
    }
    

    This seems to be caused by the internal searchObject field having lazy initialization , looking at SearchResultCollection with Reflector :

    internal UnsafeNativeMethods.IDirectorySearch SearchObject
    {
        get
        {
            if (this.searchObject == null)
            {
                this.searchObject = (UnsafeNativeMethods.IDirectorySearch) this.rootEntry.AdsObject;
            }
            return this.searchObject;
        }
    }
    

    The dispose will not close the unmanaged handle unless searchObject is initialized.

    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (((this.handle != IntPtr.Zero) && (this.searchObject != null)) && disposing)
            {
                this.searchObject.CloseSearchHandle(this.handle);
                this.handle = IntPtr.Zero;
            }
        ..
       }
    }
    

    Calling MoveNext on the ResultsEnumerator calls the SearchObject on the collection thus making sure it is disposed properly as well.

    public bool MoveNext()
    {
      ..
      int firstRow = this.results.SearchObject.GetFirstRow(this.results.Handle);
      ..
    }
    

    The leak in my application was due to some other unmanaged buffer not being released properly and the test I made was misleading. The issue is resolved now.

提交回复
热议问题