证书内存泄漏

4

我正在使用.NET 3.5。

当创建对X509Certificate的引用时,我遇到了内存泄漏问题。我使用ANTS分析器来分析结果,私有字节大小在增加,而堆中的字节数保持不变(表明这是由于未受管理代码引起的内存泄漏)。

我正在使用CRYPT32 dll来管理证书。我打开对证书存储的引用以获取一个存储句柄,该句柄是一个内部指针(intptr)。然后,我使用此存储处理程序在存储中查找证书(已本地保存)。一旦我拥有证书,我就关闭证书存储并将证书返回给调用程序。我在certclosestore中使用标志0,这使得关闭存储后保持资源处于打开状态。我相信这是导致内存泄漏的原因,因为在这里提到了它: http://msdn.microsoft.com/en-us/library/ms937035.aspx

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

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;
    }
1个回答

4
当然,你泄漏了CRYPT32资源。在你的代码片段中,我看到一个可能出现问题的地方是CertFindCertificateInStore()返回值,必须通过显式调用CertFreeCertificateContext()进行释放,但是我没有看到这样的操作。
X509Certification(IntPtr)构造函数的文档不够详细,它没有描述上下文需要有效的时间。我看到它调用了一个名为X509Utils._DuplicateCertContext()的内部方法,所以很有可能在创建对象后立即调用释放函数。
请仔细检查代码,并三重检查从CRYPT32获取的所有句柄和指针是否被释放。

感谢您的详细回复。您说得对,我在代码中没有调用 CertFreeCertificateContext 释放这个资源。在 X509Certificate 返回证书后,我会尝试一下,并希望您说得对,可以在创建后释放它。 - CorribView
它成功了 :-) 感谢您的解决方案!我已经在这上面工作了一段时间,如果没有您的帮助,我想我仍然会盯着代码看不懂。 - CorribView

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接