Weird Access Violation Exception

2020-08-11 00:19发布

问题:

I'm puzzled with an occurance of AccessViolationException. It's quite impossible (see answer) to have a clean reproduction but here goes the general idea:

class MyClass 
{
  public List<SomeType> MyMethod(List<string> arg)
  {
     // BREAKPOINT here
     // Simple stuff here, nothing fancy, no external libs used
  }
}

delegate List<SomeType> MyDelegate(List<string> arg);

... 

var myObject = new MyClass();

Func<List<string>, List<SomeType>> myFunc = myObject.MyMethod;
MyDelegate myDelegate = myObject.MyMethod;

myFunc(null)            // works fine
myDelegate(null)        // works fine
myObject.MyMethod(null) // throws AccessViolationException

The weird part is I'm not using any unsafe code. I don't have any dependencies on external libraries anywhere close (and anywhere in the whole program execution AFAIK).

The weirdest part is this is 100% reproducable and even after refactoring the code slightly, moving the method invocation elsewhere, putting extra code before it etc. - in all cases AccessViolationException is still thrown on that particular method invocation. The method is never entered when invoked directly (breakpoint is not hit). Invoking it through delegate or Func<> works fine.

Any clues as to what could cause it or how to debug it?

UPDATE

Following antiduh's question: There is no call to a virtual method from a constructor anywhere close. The actual stack trace when this happens is very simple, just two static methods and a simple instance one.

The only clue seems to be threading. There is Parallel.ForEach() and Thread.Sleep() invoked before this in program execution (not in call stack). Any clues as to how mishandled threading (with regular, managed classes) could cause AVE?

UPDATE

Narrowed it down to a VS bug, see my answer.

回答1:

This seems to be a VS bug. Have a look at this full solution. Code is simple:

using System;
using System.Collections.Generic;

namespace Foo
{
    public class MyClass
    {
        public virtual object Foo(object o1, object o2, object o3, object o4)
        {
            return new object();
        }
    }

    public sealed class Program
    {
        public static void Main(string[] args)
        {
            var myClass = new MyClass();
            object x = new object();
            myClass.Foo(null, null, null, new object()); // put a breakpoint here and once it stops, step over (F10) - AccessViolationException should be thrown in VS
        }
    }
}

The important fact I have missed before is that the code actually works fine when ran normally. Only when that particular line is being stepped over in VS (F10), the Access Violation occurs and it actually occurs in VS hosting process (even though the final stack frame is my code). It's possible to continue execution fine.

The issue happens for me on VS 2013, version 12.0.21005.1 REL. It also happens on 3 other machines I tested this on.

UPDATE

Installing .NET Framework 4.5.2 solves this.