C# 证书内存泄漏

C# 证书内存泄漏,c#,.net,memory-leaks,ssl-certificate,C#,.net,Memory Leaks,Ssl Certificate,我正在使用.NET3.5 我在创建对X509证书的引用时遇到内存泄漏。我正在使用ANTS profiler分析结果,私有字节在增加,而堆中的字节保持静态(表明这是由于非托管代码导致的内存泄漏) 我正在使用CRYPT32 dll来管理证书。我打开对cert store的引用以获取一个存储句柄,它是一个内部指针(intptr)。然后,我使用这个存储处理程序查找存储中的证书(保存在本地)。一旦我有了证书,我就关闭证书存储并将证书返回给呼叫程序。我在certclosestore中使用标志0,它在调用Cl

我正在使用.NET3.5

我在创建对X509证书的引用时遇到内存泄漏。我正在使用ANTS profiler分析结果,私有字节在增加,而堆中的字节保持静态(表明这是由于非托管代码导致的内存泄漏)

我正在使用CRYPT32 dll来管理证书。我打开对cert store的引用以获取一个存储句柄,它是一个内部指针(intptr)。然后,我使用这个存储处理程序查找存储中的证书(保存在本地)。一旦我有了证书,我就关闭证书存储并将证书返回给呼叫程序。我在certclosestore中使用标志0,它在调用CloseStore后保持打开的资源打开。我相信这就是导致内存泄漏的原因,正如这里所提到的:

但是,当我将关闭标志更改为:

CertCloseStore(storeHandle, 2)
这应该可以释放分配的资源。然而,这只会导致服务崩溃

应用程序的工作原理是验证证书等。唯一的问题是内存使用缓慢增加,需要每周左右重新启动服务。任何想法或想法都将不胜感激

public static X509Certificate CreateFromRegistry(string certificateIdent)
{
  X509Certificate certificate = null;
  IntPtr storeHandle = CertificateStore.CertOpenStore(CERT_STORE_PROV_SYSTEM, 
      0, 0,CERT_SYSTEM_STORE_LOCAL_MACHINE, "MY");;

  certificate = new X509Certificate(CertificateStore.
  FindCertInStore(certificateIdent, storeHandle));
  CertificateStore.CertCloseStore(storeHandle, 0);
  return certificate;
}



public class CertificateStore
{
    const int CERT_STORE_PROV_SYSTEM = 10;
    private static int CERT_SYSTEM_STORE_LOCAL_MACHINE = (2 << 16);
    const uint PKCS_7_ASN_ENCODING = 0x00010000;
    const uint X509_ASN_ENCODING = 0x00000001;
    const uint CERT_FIND_SUBJECT_STR = 0x00080007;
    const uint CERT_FIND_ISSUER_STR = 0x00080004;
    static uint MY_ENCODING_TYPE = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;

    [DllImport("CRYPT32", EntryPoint = "CertOpenStore",
        CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr CertOpenStore(
        int storeProvider, int encodingType,
        int hcryptProv, int flags, string pvPara);

    [DllImport("CRYPT32", EntryPoint = "CertCloseStore",
        CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern bool CertCloseStore(
        IntPtr storeProvider,
        int flags);
}

public static X509Certificate FindCertInStore
        (string trustedRootIssuerName, IntPtr storeHandle)
    {
        IntPtr hCertCntxt;
        X509Certificate theActualCertificate = null;

        if (storeHandle != IntPtr.Zero)
        {
            hCertCntxt = CertFindCertificateInStore(
               storeHandle,
               MY_ENCODING_TYPE,
               0,
               CERT_FIND_ISSUER_STR,
               trustedRootIssuerName,
               IntPtr.Zero);

            if (hCertCntxt != IntPtr.Zero)
            {
                theActualCertificate = new X509Certificate(hCertCntxt);
            }
        }
        return theActualCertificate;
    }
公共静态X509Certificate CreateFromRegistry(字符串CertificateId)
{
X509Certificate=null;
IntPtr storeHandle=CertificateStore.CertOpenStore(证书存储系统),
0,0,证书系统存储本地机器,“我的”);;
证书=新的X509证书(证书存储)。
FindCertInStore(CertificateId、storeHandle));
CertificateStore.CertCloseStore(storeHandle,0);
退货证明;
}
公共类证书存储库
{
const int CERT\u STORE\u PROV\u SYSTEM=10;

私有静态int-CERT\u-SYSTEM\u-STORE\u-LOCAL\u-MACHINE=(2当然,您正在泄漏CRYPT32资源。我在您的代码段中看到的一个直接候选项是CertFindCertificateInstance()的返回值。它必须通过显式调用CertFreeCertificateContext()来释放,我没有看到

X509Certification(IntPtr)构造函数没有很好的文档记录,它没有描述上下文需要多长时间才有效。我看到它调用了一个名为X509Utils的内部方法。\u DuplicateCertContext()的几率非常高,因此您可以在创建对象后立即调用release函数


请仔细检查代码的其余部分,并进行三次检查,确保从CRYPT32获得的所有句柄和指针都已释放。

感谢您提供的信息性回复。您是对的,我不会在代码中的任何地方调用CertFreeCertificateContext来释放此资源。在X509证书返回cert,希望您在创建后能够发布它是正确的。它成功了:-)感谢您的解决方案!我已经为此工作了一段时间,我想在没有您输入的情况下,我仍然会盯着代码看。