gpt4 book ai didi

c# - 使用 DirectorySearcher.FindAll() 时发生内存泄漏

转载 作者:IT王子 更新时间:2023-10-29 04:22:04 24 4
gpt4 key购买 nike

我有一个长时间运行的进程,需要经常在 Active Directory 上执行大量查询。为此,我一直在使用 System.DirectoryServices 命名空间,使用 DirectorySearcher 和 DirectoryEntry 类。我注意到应用程序中存在内存泄漏。

可以用这段代码重现:

while (true)
{
using (var de = new DirectoryEntry("LDAP://hostname", "user", "pass"))
{
using (var mySearcher = new DirectorySearcher(de))
{
mySearcher.Filter = "(objectClass=domain)";
using (SearchResultCollection src = mySearcher.FindAll())
{
}
}
}
}

这些类的文档说,如果不调用 Dispose(),它们将泄漏内存。我也尝试过不处理,在那种情况下它只会泄漏更多内存。我已经用框架版本 2.0 和 4.0 测试过这个有没有人遇到过这个?有任何解决方法吗?

更新:我尝试在另一个 AppDomain 中运行代码,但似乎也没有帮助。

最佳答案

尽管可能很奇怪,但似乎只有当您不对搜索结果进行任何操作时才会发生内存泄漏。修改问题中的代码如下,不会泄漏任何内存:

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

这似乎是由具有延迟初始化的内部 searchObject 字段引起的,使用 Reflector 查看 SearchResultCollection:

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

除非初始化 searchObject,否则处置不会关闭非托管句柄。

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;
}
..
}
}

在 ResultsEnumerator 上调用 MoveNext 会调用集合上的 SearchObject,从而确保它也被正确处理。

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

我的应用程序中的泄漏是由于其他一些非托管缓冲区没有被正确释放,而我所做的测试具有误导性。问题现已解决。

关于c# - 使用 DirectorySearcher.FindAll() 时发生内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5631972/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com