The code snippet below exhibits a bug I was able to isolate from production code. The program will crash with a System.AccessViolationException.
My system configuration is Visual Studio 2013 on Windows 8.1 x64. To reproduce the bug, follow these steps in Visual Studio:
- Create an empty Console Application
- Replace the entire contents of Program.cs with the code below
- Compile in Release mode, Any CPU
- Start without debugging (CTRL + F5)
The program will crash immediately, displaying an error stack trace in the Console window.
I was not able to reduce the code any further, i.e. modifying any portion of the code will make the bug disappear.
Is there any way to tell the root cause of this bug? What would be a good workaround?
using System;
using System.Threading.Tasks;
namespace ParallelBugTest
{
class Program
{
private class Value
{
public double X;
}
private class Aggregator
{
private Value myval = new Value();
public void Add()
{
// use Min() instead of Max() -> bug disappears
myval.X = Math.Max(0, myval.X);
}
}
public static void Main(string[] args)
{
Parallel.For(0, 10000, Process);
}
private static void Process(int k)
{
Value[] V = new Value[10000];
Aggregator aggregator = new Aggregator();
for (int i = 0; i < V.Length; i++)
{
V[i] = new Value();
aggregator.Add();
}
}
}
}
Math.Max is not Thread-Safe. I guess Min is working because it is faster to calculate. Locking the Max-Call works:
Fast and easier way is just to use an ordinary iif: