背景说明
1、需要对图像进行处理,图像大小为 4000*1500。
2、要在32位机器上运行。
3、使用C#。而且使用了C#版本的OpenCV,既EmguCV。
4、图片串行处理。
5、.Net版本是4.6;EmguCv版本是3.1.0.2504
现象
处理图片的时候偶尔会发生内存溢出,大概是1千张发生1次。发生溢出的图片,单独再处理,没有发生溢出。
错误信息如下所示:
异常信息: System.AccessViolationException
在 Emgu.CV.MatInvoke.cveMatCopyTo(IntPtr, IntPtr, IntPtr)
在 Emgu.CV.Mat.CopyTo(Emgu.CV.IOutputArray, Emgu.CV.IInputArray)
个人怀疑是垃圾回收的问题。
class Program
{
static void Main(string[] args)
{
int size = 2147483647; //2G
for (int i = 0; i < 100; i++)
{
try
{
/*-----------------------------
跑两个1/8的时候:
Debug 版本:可能报错也可能不报错内存溢出
1/8的时候:
Release 版本:不报错
Debug 版本:不报错
1/4的时候:
Release 版本:不报错
Debug 版本:从第2次开始报错内存溢出
1/2的时候:
Release 版本:从第2次开始报错内存溢出
Debug 版本:从第2次开始报错内存溢出
-----------------------------*/
double rate = 1.0 / 8;
byte[] memory = new byte[(int)(size * rate)];
memory = null;
//byte[] memory2 = new byte[(int)(size * rate)];
//memory2 = null;
Console.WriteLine("成功");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
while (true)
{
}
}
}
然后用C++跑等价的代码,就没有那些溢出的现象。
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int size = 2147483647; //2G
for (int i = 0; i < 100; i++)
{
try
{
double rate = 1.0/4 ;
char* memory = new char[(int)(size * rate)];
delete[] memory;
memory = NULL;
cout << "成功"<<"\n";
}
catch(exception ex)
{
cout<<"失败:" << ex.what() << "\n";
}
}
while (true)
{
}
}
问题
1、是不是垃圾回收的问题呢?还是我用的EmguCv版本有BUG。
2、如果是垃圾回收问题。如何让C# 像 C++那样快速回收申请的大块内存,避免内存溢出。网上说赋值null或者用下面的语句强制回收好像都没有什么效果。
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
3、多谢指教