C# 模拟内存泄漏
上有一个关于如何使用.net 4.0进行模拟的示例。为了便于使用,我们在继承IDisposable的类中使用了这个示例。然而,当我们在asp.net web应用程序中使用此类时,我们注意到performance monitor中的池分页字节有轻微但稳定的增加。一周后,应用程序崩溃 我尝试了模拟类的不同实现,使用和作为引用,但它们都显示了相同的漏洞 这个漏洞是从哪里来的?windows api有问题吗?我们正在运行Windows 2008 R2 这是模拟类的当前版本:C# 模拟内存泄漏,c#,asp.net,winapi,memory-leaks,C#,Asp.net,Winapi,Memory Leaks,上有一个关于如何使用.net 4.0进行模拟的示例。为了便于使用,我们在继承IDisposable的类中使用了这个示例。然而,当我们在asp.net web应用程序中使用此类时,我们注意到performance monitor中的池分页字节有轻微但稳定的增加。一周后,应用程序崩溃 我尝试了模拟类的不同实现,使用和作为引用,但它们都显示了相同的漏洞 这个漏洞是从哪里来的?windows api有问题吗?我们正在运行Windows 2008 R2 这是模拟类的当前版本: public class I
public class Impersonator : IDisposable
{
public Impersonator(string username, string domain, string password)
{
if (!ImpersonateValidUser(username, domain, password))
{
throw new SecurityException("Could not impersonate. Wrong username / password");
}
}
public void Dispose()
{
UndoImpersonation();
}
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);
private const int LOGON32_PROVIDER_DEFAULT = 0;
private const int LOGON32_LOGON_INTERACTIVE = 2; //This parameter causes LogonUser to create a primary token.
private WindowsImpersonationContext impersonatedUser;
private bool ImpersonateValidUser(string username, string domain, string password)
{
SafeTokenHandle safeTokenHandle;
// Call LogonUser to obtain a handle to an access token.
bool success = LogonUser(username, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out safeTokenHandle);
if (success)
{
using (safeTokenHandle)
{
// Use the token handle returned by LogonUser.
WindowsIdentity newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle());
impersonatedUser = newId.Impersonate();
}
}
return success;
}
private void UndoImpersonation()
{
// Releasing the context object stops the impersonation
if (impersonatedUser != null)
{
impersonatedUser.Undo();
impersonatedUser.Dispose();
}
}
}
public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private SafeTokenHandle() : base(true)
{
}
[DllImport("kernel32.dll")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr handle);
protected override bool ReleaseHandle()
{
return CloseHandle(handle);
}
}
这是使用该类不同版本的两个Web服务器的性能监视器图:
当我们禁用该类并通过web.config使用全局模拟时,这些行是完全平坦的
更新 我已经做了一个测试应用程序,成功地重现了这个问题。可在此下载: 超过18小时的结果如下所示:
很难说。至少,
WindowsIdentity
本身也是一个IDisposable
,而且newId
变量永远不会被处理掉。此外,我还要检查是否正确地处理了模拟程序
类的所有使用。该类的所有使用都是在using语句中进行的,因此应该是安全的。虽然newId变量调用得很好,但我会修复它并将其发送给明天的测试。更新的结果相同。我还在我们的开发环境中制作了一个测试应用程序,但我似乎无法复制那里的漏洞。经过100万次模拟后,池分页字节保持不变,因此我真的不知道从这里走到哪里。我也不知所措。如果没有额外的信息(并且考虑到场景,最有可能是:没有完整的应用程序),就无法判断。我几乎不希望处理WindowsIdentity会起到什么作用,但是,唉,我现在已经成功地复制了漏洞,现在在我的问题中找到了完整的应用程序。在我更改了测试应用程序以更好地复制生产环境的行为(在模拟过程中在网络共享上创建和删除文件)之后,我已经看过你的代码和SafeHandleZeroOrMinusOneIsInvalid(通过Reflector)的实现。我肯定我可能错过了一些东西,但我不清楚CloseHandle或ReleaseHandle是从哪里调用的。您是否希望由SafeTokenHandle上继承的Dispose方法调用它?我不知道它是如何工作的,我只是假设它是这样的,因为它是从上面链接中的microsoft站点复制的。我添加了几行调试,模拟完成后会调用它,但我只知道这些。考虑到您所说的以及其他示例显式关闭句柄,那么这似乎不是问题。你有MSDN订阅吗?如果是这样的话,您可以利用Microsoft支持事件获得一些额外的帮助。是的,我们有MSDN订阅,但由于我似乎无法在本地重现问题,我认为这不会有帮助。尽管如此,我更新了我的问题,提供了有关如何重现泄漏的信息。