Weird Access Violation Exception - c#

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.

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.

Related

StackTrace.GetFrame throws NullReferenceException in Release build but works in Debug build

I wrote a class which is intended to provide robust logging messages. One of the features I want to include is to include the class and method from which a call to generate a log message originated.
The problem I'm having is that StackTrace.GetFrame behaves inconsistently between debug and release builds. As far as I can tell, it behaves as expected when I execute programs from VS in debug. When I execute a release build deliverable, StackTrace.GetFrame throws a NullReferenceException.
Here's a simplified example of my code:
using Logging;
namespace MyApp
{
class Program
{
public static void Main(string[] args)
{
Logger Log = new Log(Level.INFO);
Log.Info(#"Hello, world!");
}
}
}
namespace Logging
{
class Logger
{
//Assume a constructor
public void Info(string message)
{
//We will need to go 3 method calls back from StandardEntry()
//to get the name of the method which called Log.Info
StandardEntry(text, Level.INFO, 3);
}
//This method is called by Logger.Info, Logger.Error, etc
private void StandardEntry(string message, Level entryLevel, int frameCount)
{
if (entryLevel >= this.level)
{
string message = $"[{CallingMethod(frameCount)}] {<entryLevel.ToString()>} {message}\r\n";
File.AppendText(this.LogPath, message);
}
}
private string CallingMethod()
{
string retVal;
StackTrace st = new StackTrace();
StackFrame sf = st.GetFrame(frameCount);
MethodBase callingMethod = sf.GetMethod();
return $"{callingMethod.ReflectedType.Name}.{callingMethod.Name}";
}
}
}
I've tried playing around with the value I'm passing in for frameCount, but a lower number returns a method call that is still within the Logger class. I need the method that actually called Log.Info
When running a release deliverable, Log.Info() in Program.Main throws a NullReferenceException, which leads me to believe that it's trying to access a stack frame index that is beyond the scope of the invoked executable.
When I debug in Visual Studio, there is no exception and CallingMethod() returns the expected expression.
In release builds, one of the optimizations the JIT compiler performs is inlining methods, i.e. inserting the code of a called method directly into the method calling it. This means that some methods may simply disappear from the stack trace you're seeing.
What you can do instead is add parameters to the Info method together with the caller information attributes which are made for scenarios like this. The C# compiler will automatically fill in the information for those parameters at compile time, so they're not affected by runtime optimizations.
It seems that class CallerMemberNameAttribute is what you actually needs.

Why Dispose is not called even with using-statement?

I have this console application (.NET Framework 4.5.2):
class Program
{
static void Main(string[] args)
{
using (var result = new Result())
{
result.Test();
}
}
}
public class Result : IDisposable
{
public void Test()
{
int a = 1;
int b = 1 / (a - 1);
}
public void Dispose()
{
Console.WriteLine("Dispose");
}
}
Why Dispose method is not called? A breakpoint is not hit in Dispose after the DivideByZero-exception and there is no output on the console (because the app exits).
As per MS Docs: try-finally (C# Reference)
Within a handled exception, the associated finally block is guaranteed
to be run. However, if the exception is unhandled, execution of the
finally block is dependent on how the exception unwind operation is
triggered. That, in turn, is dependent on how your computer is set up.
As you are not catching the DivideByZero exception and let it be unhandled, on your machine and setup it must be bringing down the application before any other line of code is run and therefore not running the finally block.
As #Evk has pointed out in below comment, if I run it without attaching debugger, it unwinds the exceptions correctly and executes the finally block. Learn something new everyday.
As per Eric Lippert's answer to Finally Block Not Running?
Think about how awful that situation is: something unexpected has
happened that no one ever wrote code to handle. Is the right thing to
do in that situation to run even more code, that was probably also not
built to handle this situation? Possibly not. Often the right thing to
do here is to not attempt to run the finally blocks because doing so
will make a bad situation even worse. You already know the process is
going down; put it out of its misery immediately.
In a scenario where an unhandled exception is going to take down the
process, anything can happen. It is implementation-defined what
happens in this case: whether the error is reported to Windows error
reporting, whether a debugger starts up, and so on. The CLR is
perfectly within its rights to attempt to run finally blocks, and is
also perfectly within its rights to fail fast. In this scenario all
bets are off; different implementations can choose to do different
things.

Method being skipped?

Ok. The problem I'm having is a little difficult to explain, but essentially my issue is the method that is responsible for filling a dataset is being skipped. The debugger hits the line of code in question, but skips right over it. No chance of stepping into or what not.
// Class A
private myTableDS _dsTable; // myTableDS.xsd
private classB _clsB;
protected override void OnLoad(EventArgs e)
{
if (_dsTable == null)
{
_dsTable = _clsB.LoadThisTable(); // The culprit
}
// More logic here. Mindblowing. It is.
}
// Class B
public myTableDS LoadThisTable()
{
// Magic here
}
So the debugger hits the line _dsTable = _clsB.LoadThisTable(); and jumps out. Taking me back to the next line in the code that invoked "onload" in the first place. So any and all logic beneath _dsTables = _ASIO.LoadASTables(); is skipped.
Thoughts?
Typically, when the debugger is skipping code, it has something to do with threading (which doesn't appear to be the case here), a type load exception (missing assembly), or a different version of the code being deployed than what is being debugged.
If the latter cases are the problem, the solution is making sure the very latest assemblies are actually deployed to the environment you're debugging.
Also, try putting a Debbugger.Launch() statement in myTableDS.LoadThisTable() and setting Visual Studio up so that the debugger breaks when exceptions are thrown (not just unhandled).

How do I add support for typed calls to a remote COM+ application

I am in the process of replacing a COM+ hosted application with a .Net variant.
The steps I took are roughly:
Generate an Interop assembly of the old dll
Create a new class in C# .Net that derives from ServicedComponent and implements the IMyClass interface from the interop.
I have annotated the class with a [Guid("...")] and a [ProgId("...")] attribute to match the class in the old dll
The end result looks like this:
[ProgId("MyComponent")]
[Guid("...")]
public class MyClass : ServicedComponent, IMyClass
{
public MyClass()
{
}
public object Open(string arg1, string arg2)
{
/* trace arguments*/
}
public object Run()
{
/* implementation here */
}
public void Close()
{
return;
}
}
This assembly is installed on a remote machine using regsvcs.exe
Now most clients use code similar to this unittest code:
Type typeFromProgID = Type.GetTypeFromProgID("MyComponent", "remoteMachine", true);
dynamic comInstance = Activator.CreateInstance(typeFromProgID);
comInstance.Open(string.Empty, string.Empty);
comInstance.Run();
comInstance.Close();
This works perfectly, the .Net tracing on the remote machine tells me everything is working as it should. Other clients use code similar to this:
Type typeFromProgID = Type.GetTypeFromProgID("MyComponent", "remoteMachine", true);
MyClass comInstance = (MyClass)Activator.CreateInstance(typeFromProgID);
comInstance.Open(string.Empty, string.Empty);
comInstance.Run();
comInstance.Close();
The first line is the same and seems to work fine, the rest acts weird. The VS debugger shows the lines are being executed. The remoteMachine shows that no methods are being executed.
The last call to Close(), which actually just returns, throws an exception:
System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Result StackTrace:
at Interop.MyComponent.IMyClass.Close()
at UnitTestProject1.UnitTest1.temp()
What have I missed in my implementation to support this last (typed) scenario?
This sounds like mismatched metadata, e.g. marshaling is different between the one that happens with the original type library and the one that happens with your server registered .NET assembly.
My guess is that the untyped case runs well because it depends solely on IDispatch, which .NET implements quite well, but the typed test fails (and I'm surprised it doesn't fail earlier) because of this mismatch.

NullReferenceException in finalizer during MSTest

(I know, this is a ridiculously long question. I tried to separate the question from my investigation so far, so it's slightly easier to read.)
I'm running my unit tests using MSTest.exe. Occasionally, I see this test error:
On the individual unit test method: "The agent process was stopped while the test was running."
On the entire test run:
One of the background threads threw exception:
System.NullReferenceException: Object reference not set to an instance of an object.
at System.Runtime.InteropServices.Marshal.ReleaseComObject(Object o)
at System.Management.Instrumentation.MetaDataInfo.Dispose()
at System.Management.Instrumentation.MetaDataInfo.Finalize()
So, here's what I think I need to do: I need to track down what is causing the error in MetaDataInfo, but I'm drawing a blank. My unit test suite takes over half an hour to run, and the error doesn't happen every time, so it's hard to get it to reproduce.
Has anyone else seen this type of failure in running unit tests? Were you able to track it down to a specific component?
Edit:
The code under test is a mix of C#, C++/CLI, and a little bit of unmanaged C++ code. The unmanaged C++ is used only from the C++/CLI, never directly from the unit tests. The unit tests are all C#.
The code under test will be running in a standalone Windows Service, so there's no complication from ASP.net or anything like that. In the code under test, there's threads starting & stopping, network communication, and file I/O to the local hard drive.
My investigation so far:
I spent some time digging around the multiple versions of the System.Management assembly on my Windows 7 machine, and I found the MetaDataInfo class in System.Management that's in my Windows directory. (The version that's under Program Files\Reference Assemblies is much smaller, and doesn't have the MetaDataInfo class.)
Using Reflector to inspect this assembly, I found what seems to be an obvious bug in MetaDataInfo.Dispose():
// From class System.Management.Instrumentation.MetaDataInfo:
public void Dispose()
{
if (this.importInterface == null) // <---- Should be "!="
{
Marshal.ReleaseComObject(this.importInterface);
}
this.importInterface = null;
GC.SuppressFinalize(this);
}
With this 'if' statement backwards, MetaDataInfo will leak the COM object if present, or throw a NullReferenceException if not. I've reported this on Microsoft Connect: https://connect.microsoft.com/VisualStudio/feedback/details/779328/
Using reflector, I was able to find all uses of the MetaDataInfo class. (It's an internal class, so just searching the assembly should be a complete list.) There is only one place it is used:
public static Guid GetMvid(Assembly assembly)
{
using (MetaDataInfo info = new MetaDataInfo(assembly))
{
return info.Mvid;
}
}
Since all uses of MetaDataInfo are being properly Disposed, here's what's happening:
If MetaDataInfo.importInterface is not null:
static method GetMvid returns MetaDataInfo.Mvid
The using calls MetaDataInfo.Dispose
Dispose leaks the COM object
Dispose sets importInterface to null
Dispose calls GC.SuppressFinalize
Later, when the GC collects the MetaDataInfo, the finalizer is skipped.
.
If MetaDataInfo.importInterface is null:
static method GetMvid gets a NullReferenceException calling MetaDataInfo.Mvid.
Before the exception propagates up, the using calls MetaDataInfo.Dispose
Dispose calls Marshal.ReleaseComObject
Marshal.ReleaseComObject throws a NullReferenceException.
Because an exception is thrown, Dispose doesn't call GC.SuppressFinalize
The exception propagates up to GetMvid's caller.
Later, when the GC collects the MetaDataInfo, it runs the Finalizer
Finalize calls Dispose
Dispose calls Marshal.ReleaseComObject
Marshal.ReleaseComObject throws a NullReferenceException, which propagates all the way up to the GC, and the application is terminated.
For what it's worth, here's the rest of the relevant code from MetaDataInfo:
public MetaDataInfo(string assemblyName)
{
Guid riid = new Guid(((GuidAttribute) Attribute.GetCustomAttribute(typeof(IMetaDataImportInternalOnly), typeof(GuidAttribute), false)).Value);
// The above line retrieves this Guid: "7DAC8207-D3AE-4c75-9B67-92801A497D44"
IMetaDataDispenser o = (IMetaDataDispenser) new CorMetaDataDispenser();
this.importInterface = (IMetaDataImportInternalOnly) o.OpenScope(assemblyName, 0, ref riid);
Marshal.ReleaseComObject(o);
}
private void InitNameAndMvid()
{
if (this.name == null)
{
uint num;
StringBuilder szName = new StringBuilder {
Capacity = 0
};
this.importInterface.GetScopeProps(szName, (uint) szName.Capacity, out num, out this.mvid);
szName.Capacity = (int) num;
this.importInterface.GetScopeProps(szName, (uint) szName.Capacity, out num, out this.mvid);
this.name = szName.ToString();
}
}
public Guid Mvid
{
get
{
this.InitNameAndMvid();
return this.mvid;
}
}
Edit 2:
I was able to reproduce the bug in the MetaDataInfo class for Microsoft. However, my reproduction is slightly different from the issue I'm seeing here.
Reproduction: I try to create a MetaDataInfo object on a file that isn't a managed assembly. This throws an exception from the constructor before importInterface is initialized.
My issue with MSTest: MetaDataInfo is constructed on some managed assembly, and something happens to make importInterface null, or to exit the constructor before importInterface is initialized.
I know that MetaDataInfo is created on a managed assembly, because MetaDataInfo is an internal class, and the only API that calls it does so by passing the result of Assembly.Location.
However, re-creating the issue in Visual Studio meant that it downloaded the source to MetaDataInfo for me. Here's the actual code, with the original developer's comments.
public void Dispose()
{
// We implement IDisposable on this class because the IMetaDataImport
// can be an expensive object to keep in memory.
if(importInterface == null)
Marshal.ReleaseComObject(importInterface);
importInterface = null;
GC.SuppressFinalize(this);
}
~MetaDataInfo()
{
Dispose();
}
The original code confirms what was seen in reflector: The if statement is backwards, and they shouldn't be accessing the managed object from the Finalizer.
I said before that because it was never calling ReleaseComObject, that it was leaking the COM object. I read up more on the use of COM objects in .Net, and if I understand it properly, that was incorrect: The COM object isn't released when Dispose() is called, but it is released when the garbage collector gets around to collecting the Runtime Callable Wrapper, which is a managed object. Even though it's a wrapper for an unmanaged COM object, the RCW is still a managed object, and the rule about "don't access managed objects from the finalizer" should still apply.
Try to add the following code to your class definition:
bool _disposing = false // class property
public void Dispose()
{
if( !disposing )
Marshal.ReleaseComObject(importInterface);
importInterface = null;
GC.SuppressFinalize(this);
disposing = true;
}
If MetaDataInfo uses the IDisposable pattern, then there should also be a finalizer (~MetaDataInfo() in C#). The using statement will make sure to call Dispose(), which sets the importInterface to null. Then when the GC is ready to finalize, the ~MetaDataInfo() is called, which would normally call Dispose (or rather the overload taking a bool disposing: Dispose(false)).
I would say that this error should turn up quite often.
Are you trying to fix this for your tests? If so, rewrite your using. Don't dispose of it yourself but write some code to use reflection to access the private fields and dispose of them correctly and then call GC.SuppressFinalize to prevent the finalizer from running.
As a brief aside (loved your investigation btw) you state that Dispose calls Finalize. It's the other way round, Finalize when invoked by the GC calls Dispose.

Categories