AccessViolationException with Parallel.For ()

The code snippet below shows an error that I was able to isolate from the production code. The program will crash with System.AccessViolationException

.

My system config is Visual Studio 2013 on Windows 8.1 x64. To reproduce the error, follow these steps in Visual Studio:

  • Creating an empty console application
  • Replace all contents of Program.cs with below code
  • Compile in Release mode , any processor
  • Run without debugging (CTRL + F5)

The program will crash immediately, displaying the error stack trace in the console window.

I was unable to make the code smaller anymore, i.e. changing any part of the code will clear the error.

Is there a way to report the root cause of this error? What would be a good way?

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();
            }
        }
    }
}

      

+3


source to share


2 answers


Everything in your code is thread safe as there is no shared state between threads (each iteration has its own Aggregator

and array Value

, and you don't use any fields static

).

Even if your code was not thread safe, it doesn't do anything unsafe (i.e., it works directly with memory), which should be the only way to get it AccessViolationException

.



Because of this, I believe this is a bug in the CLR and you should report it (click the "submit feedback" link after logging in).

0


source


Math.Max ​​is not thread safe. I think Min works because it is faster to compute. Blocking of Max-Call:

    private static Object lockObj = new Object();

    private class Value
    {
        public double X;
    }

    private class Aggregator
    {
        private Value myval = new Value();

        public void Add()
        {
            // use Min() instead of Max() -> bug disappears
            lock (lockObj)
            { 
                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();
        }
    }

      



A quick and easy way is to just use a regular iif:

        public void Add()
        {
            // use Min() instead of Max() -> bug disappears
            myval.X = myval.X > 0 ? myval.X : 0;
        }

      

-1


source







All Articles