2012-08-16 19 views
2

我正在使用.NET 3.5。證書內存泄漏

創建對X509Certificate的引用時遇到內存泄漏。我使用ANTS分析器來分析結果,並且私有字節正在增加,而堆中的字節保持靜態(表示由於非託管代碼導致的內存泄漏)。

我正在使用CRYPT32 DLL來管理證書。我打開一個對cert store的引用來獲得一個內部指針(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; 
    } 

回答

3

那麼,你正在泄漏CRYPT32資源當然。我在你的代碼片段中看到的一個直接候選者是CertFindCertificateInStore()的返回值。它必須通過顯式調用CertFreeCertificateContext()來釋放,我沒有看到它。

X509Certification(IntPtr)構造函數沒有很好地記錄,它沒有描述上下文需要有效的時間。我看到它調用一個名爲X509Utils._DuplicateCertContext()的內部方法,所以很有可能在創建對象後立即調用release函數。

請檢查您的代碼的其餘部分,使用精細梳齒和三重檢查來檢查您從CRYPT32獲取的所有句柄和指針是否已發佈。

+0

謝謝您提供的內容豐富的答覆。你是對的,我不會在我的代碼中的任何地方調用CertFreeCertificateContext來釋放這個資源。在X509Certificate返回證書之後,我會給它一個提示,希望你能夠在創建它之後釋放它。 – CorribView 2012-08-16 13:04:46

+0

它的工作原理:-) 感謝您的解決方案!我正在研究這一段時間,認爲我仍然會在沒有您的輸入的情況下盯着代碼。 – CorribView 2012-08-16 14:18:19