未映像的代码在通过IIS而非控制台应用程序调用时会泄漏内存
本文关键字:调用 应用程序 控制台 内存 泄漏 代码 映像 IIS | 更新日期: 2023-09-27 18:28:38
我有一个用C编写的非托管库(内部也使用"英特尔MKL"库),它在WCF web服务中使用。直接PInvoke用于调用公开的方法,库调用返回一个指向双数组的指针,该指针在对指针调用free()之前被复制到C#中的托管数组。
double* xStars = null;
metaData meta = new metaData();
double[] output = null;
bool hasError;
string errorMessage;
try
{
int errCode = someCFunction(...some params...
&xStars,
&meta);
output = new double[meta.ArrayLength];
for (int j = 0; j < meta.ArrayLength; j++)
{
output[j] = (xStars[j]);
}
}
catch (Exception e)
{
WriteToEventLog();
throw;
}
finally
{
//Also in the C library
//Calls free(void *)
freeDoubleArray(&xStars);
freeMeta(&meta);
}
我有测试套件,可以通过调用
- IIS作为web服务调用或
- 控制台应用程序,它运行所有其他业务逻辑,但不作为WS操作
一个较小的控制台应用程序,它只练习执行PInvoke 的类
当通过控制台应用程序(2)运行时,所使用的启动内存约为50MB,即使在循环中调用了100次底层C代码后,也能保持相当稳定
- 当通过控制台应用程序(2)运行时,启动内存更小,约为24MB,在100次调用后保持稳定
- 当通过IIS运行时,即使在服务启动时,内存使用量也在150-200 MB左右,并且每次调用C库时都会不断增加。它最终达到IIS回收它的地步,因为使用的内存超过了设置的限制
IIS中使用它的方式有什么问题?控制台应用程序(2)基本上是所有的代码,但只是作为独立的应用程序而不是web服务运行。在这种情况下,应用程序不会出现任何内存泄漏或过度使用。
到目前为止,我所做的事情是为了了解根本原因:
- 使用性能监视器对所有堆中的专用字节和GC字节进行配置。托管内存的使用量在进程启动时攀升,在整个测试过程中几乎保持不变,而私有字节在第一次调用时使用的峰值为100MB,并且在测试的每次迭代中都保持小幅增加
- 使用Debug-Diag来分析非托管内存泄漏,在IIS工作进程使用的500 MB内存中,Debug-Diag表示C库有大约43 MB未释放的内存,它认为这是一个泄漏,但没有解释其余的内存在哪里使用
- 我使用了ANTS内存探查器,它表明大部分内存是非托管的,托管内存的使用情况最差,在30 MB以内
我想我没有足够的代表点来发布图片,或者我本可以发布性能监视器的屏幕截图。编写C代码的人认为这是IIS问题(或与web服务C#代码有关),并指出当在独立应用程序中使用时,没有任何明显的泄漏。我使用的调试工具似乎表明情况并非如此。
有什么建议可以告诉我下一步该怎么做来找出问题所在吗?
如果ANTS内存探查器已识别出一个"主要内存块"已分配给非托管代码,而您预计不会使用非托管内存,那么这将是开始调查的好地方。
如果取消注释"freeDoubleArray(&xStars);"answers"freeMeta(&meta);"会发生什么?您在控制台应用程序中的行为是否与ISS web服务类似?
如果在finally块的末尾强制执行GC收集,会发生什么?您的ISS web服务的行为是否与控制台应用程序类似?