我正在使用.NET 3.5。
创建对X509Certificate的引用时,我遇到内存泄漏。我正在使用ANTS分析器来分析结果,并且私有字节正在增加,而堆中的字节保持静态(表明由于非托管代码而导致内存泄漏)。
我正在使用CRYPT32 dll来管理证书。我打开一个对cert store的引用来获取一个内部指针(intptr)的存储句柄。然后我使用此存储处理程序在存储中查找证书(本地保存)。获得证书后,我关闭证书库并将证书返回给调用程序。我在certclosestore中使用标志0,它在调用close存储后保持打开资源。我相信这是导致内存泄漏的原因,如下所述: 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;
}
答案 0 :(得分:3)
当然,你正在泄露CRYPT32资源。我在你的代码片段中看到的一个直接候选者是CertFindCertificateInStore()的返回值。它必须通过显式调用CertFreeCertificateContext()来释放,我没有看到。
X509Certification(IntPtr)构造函数没有很好地记录,它没有描述上下文需要多长时间才能生效。我看到它调用了一个名为X509Utils._DuplicateCertContext()的内部方法,因此你可以在创建对象后立即调用release函数。
请使用细齿梳检查其余代码,并检查所有从CRYPT32获得的句柄和指针是否已释放。