我已经与EMGU+OpenCV合作相当长一段时间,并遇到了这个AccessViolationException神秘事件。
首先是代码:
class AVE_Simulation
{
public static int Width = 7500;
public static int Height = 7500;
public static Emgu.CV.Image<Rgb, float>[] Images;
static void Main(string[] args)
{
int N = 50;
int Threads = 5;
Images = new Emgu.CV.Image<Rgb, float>[N];
Console.WriteLine("Start");
ParallelOptions po = new ParallelOptions();
po.MaxDegreeOfParallelism = Threads;
System.Threading.Tasks.Parallel.For(0, N, po, new Action<int>((i) =>
{
Images[i] = GetRandomImage();
Console.WriteLine("Prossing image: " + i);
Images[i].SmoothBilatral(15, 50, 50);
GC.Collect();
}));
Console.WriteLine("End");
}
public static Emgu.CV.Image<Rgb, float> GetRandomImage()
{
Emgu.CV.Image<Rgb, float> im = new Emgu.CV.Image<Rgb, float>(Width, Height);
float[, ,] d = im.Data;
Random r = new Random((int)DateTime.Now.Ticks);
for (int y = 0; y < Height; y++)
{
for (int x = 0; x < Width; x++)
{
d[y, x, 0] = (float)r.Next(255);
d[y, x, 1] = (float)r.Next(255);
d[y, x, 2] = (float)r.Next(255);
}
}
return im;
}
}
代码很简单。分配一个图像数组。生成一个随机图像并填充随机数。在该图像上执行双边滤波器。就这些。如果我在单个线程中执行此程序(Threads=1),则一切正常,没有问题。但是,如果我将并发线程数提高到5,则很快就会出现AccessViolationException的异常。
我查看了OpenCV代码,并验证了OpenCV侧面没有进行任何分配,也查看了EMGU代码以搜索未固定对象或其他问题,一切似乎都正确。
一些注意事项:
1. 如果删除GC.Collect(),则AccessViolationException的异常会更少,但最终仍会发生。 2. 这仅在Release模式下发生。在Debug模式下,我没有遇到任何异常。 3. 虽然每个图像为675MB,但分配没有问题(我有很多内存),如果系统内存不足,则会抛出OutOfMemoryException异常。 4. 我使用双边滤波器,但我也使用其他滤波器/函数时出现这种异常。
感谢任何帮助。我已经试图修复这个问题已经超过一个星期了。
i7(无超频),Win7 64位,32GB RAM,VS 2010,Framework 4.0,OpenCV 2.4.3
栈:
Start
Prossing image: 20
Prossing image: 30
Prossing image: 40
Prossing image: 0
Prossing image: 10
Prossing image: 21
Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at Emgu.CV.CvInvoke.cvSmooth(IntPtr src, IntPtr dst, SMOOTH_TYPE type, Int32 param1, Int32 param2, Double param3, Double param4)
at TestMemoryViolationCrash.AVE_Simulation.<Main>b__0(Int32 i) in C:\branches\1.1\TestMemoryViolationCrash\Program.cs:line 32
at System.Threading.Tasks.Parallel.<>c__DisplayClassf`1.<ForWorker>b__c()
at System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask)
at System.Threading.Tasks.Task.<>c__DisplayClass10.<ExecuteSelfReplicating>b__f(Object param0)
at System.Threading.Tasks.Task.Execute()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot)
at System.Threading.Tasks.Task.ExecuteEntry(Boolean bPreventDoubleExecution)
at System.Threading.Tasks.ThreadPoolTaskScheduler.TryExecuteTaskInline(Task task, Boolean taskWasPreviouslyQueued)
at System.Threading.Tasks.TaskScheduler.TryRunInline(Task task, Boolean taskWasPreviouslyQueued)
at System.Threading.Tasks.Task.InternalRunSynchronously(TaskScheduler scheduler, Boolean waitForCompletion)
at System.Threading.Tasks.Parallel.ForWorker[TLocal](Int32 fromInclusive, Int32 toExclusive, ParallelOptions parallelOptions, Action`1 body, Action`2 bodyWithState, Func`4 bodyWithLocal, Func`1 loc
alInit, Action`1 localFinally)
at System.Threading.Tasks.Parallel.For(Int32 fromInclusive, Int32 toExclusive, ParallelOptions parallelOptions, Action`1 body)
at TestMemoryViolationCrash.AVE_Simulation.Main(String[] args) in C:\branches\1.1\TestMemoryViolationCrash\Program.cs:line 35
Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at Emgu.CV.CvInvoke.cvSmooth(IntPtr src, IntPtr dst, SMOOTH_TYPE type, Int32 param1, Int32 param2, Double param3, Double param4)
at TestMemoryViolationCrash.AVE_Simulation.<Main>b__0(Int32 i) in C:\branches\1.1\TestMemoryViolationCrash\Program.cs:line 32
at System.Threading.Tasks.Parallel.<>c__DisplayClassf`1.<ForWorker>b__c()
at System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask)
at System.Threading.Tasks.Task.<>c__DisplayClass10.<ExecuteSelfReplicating>b__f(Object param0)
at System.Threading.Tasks.Task.Execute()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot)
at System.Threading.Tasks.Task.ExecuteEntry(Boolean bPreventDoubleExecution)
at System.Threading.ThreadPoolWorkQueue.Dispatch()
Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at Emgu.CV.CvInvoke.cvSmooth(IntPtr src, IntPtr dst, SMOOTH_TYPE type, Int32 param1, Int32 param2, Double param3, Double param4)
at TestMemoryViolationCrash.AVE_Simulation.<Main>b__0(Int32 i) in C:\branches\1.1\TestMemoryViolationCrash\Program.cs:line 32
at System.Threading.Tasks.Parallel.<>c__DisplayClassf`1.<ForWorker>b__c()
at System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask)
at System.Threading.Tasks.Task.<>c__DisplayClass10.<ExecuteSelfReplicating>b__f(Object param0)
at System.Threading.Tasks.Task.Execute()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot)
at System.Threading.Tasks.Task.ExecuteEntry(Boolean bPreventDoubleExecution)
at System.Threading.ThreadPoolWorkQueue.Dispatch()
Press any key to continue . . .