Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

System.AccessViolationException #49

Closed
halittiryaki opened this issue Oct 13, 2017 · 13 comments
Closed

System.AccessViolationException #49

halittiryaki opened this issue Oct 13, 2017 · 13 comments

Comments

@halittiryaki
Copy link

After I manually patch a type, I can't instantiate a new object of that type. Getting a System.AccessViolationException.

var a = new Test();

var harmony = HarmonyInstance.Create("com.company.project.product");
var original = typeof(Test).GetMethod("Call");
var prefix = typeof(Patch).GetMethod("Before");
var postfix = typeof(Patch).GetMethod("After");
harmony.Patch(original, new HarmonyMethod(prefix), new HarmonyMethod(postfix));

var b = new Test();

var y = a.Call();
var z = b.Call();

having the var b = new Test(); initialization right after var a works.

Is this expected behaviour, or am I missing something?

Thanks

@halittiryaki
Copy link
Author

Seems to be a .NET 4+ issue. Works with 3.5. Any quickfix ideas?

@pardeike
Copy link
Owner

Did you test with the master version?

@halittiryaki
Copy link
Author

yes. just cloned again.

and release mode seems to be not supported at all?

@pardeike
Copy link
Owner

The release is currently for unity (mono) only. I’m working on incorporating the pull requests to make an new master.

@halittiryaki
Copy link
Author

so next master branch will support release mode and .net 4+?

@halittiryaki
Copy link
Author

kinda sorted it out. The master branch downloaded as zip doesn't include the AccessViolation Fix. It doesn't even contain the NativeLibrary.cs.
Seems like it was reverted by hcoona.

however, git clone .. gets a master branch with the fix included, but still not solving the AccessViolation Exception on my Windows 10 x64, with .NET 4.0+ versions.

@pardeike
Copy link
Owner

Maybe this is related to the content of your patch? Usually, access violations appear when patching, not during runtime. Or you are running this in a specific environment that enforces access rules more aggressively. Can you provide more details?

@halittiryaki
Copy link
Author

halittiryaki commented Oct 15, 2017

this is the content of my patch / target class, in a clean Console app project just attached to the Harmony solution:

public class Test
    {
        public string Call()
        {
            return "asd";
        }
    }

    public class Patch
    {
        public static bool Before(ref object __result)
        {
            Console.WriteLine("Before..");
            __result = "asdfa";
            return false;
        }
        public static void After()
        {
            Console.WriteLine("After");
        }
    }

the difference which makes this patch work is either:

  • in .Net 4+; have all new Test() instantiations before patching
  • or .Net 3.5
  • all .net versions; only Debug mode support (release mode completely ignoring patch, no exceptions either. the original target method being invoked as if there was no patch at all.)

my environment is windows 10 x64 (no vbox) with VS 2015.

that enforces access rules more aggressively

where to look further?

thanks

@halittiryaki
Copy link
Author

trying public static bool Before(ref string __result) just crashed the whole OS with a bluescreen

@pardeike
Copy link
Owner

It should not. The prefix is called from within the main method as a subroutine and the ref argument is put on the call stack as an ordinary IL code. All you should get is a an exception from the CIL execution which cannot drag your binary down like you describe.

@halittiryaki
Copy link
Author

yes it shouldn't normally. happened once strangely.. cant get it there again without code change

@pardeike
Copy link
Owner

Cannot reproduce with latest version

@pardeike
Copy link
Owner

This is my test case. Done in VS2017, with .NET 4.6.1 and Release build:

using Harmony;
using System;

namespace HarmonyConsoleApp
{
	class Program
	{
		static void Main(string[] args)
		{
			var a = new Test();

			var harmony = HarmonyInstance.Create("com.company.project.product");
			var original = typeof(Test).GetMethod("Call");
			var prefix = typeof(Patch).GetMethod("Before");
			var postfix = typeof(Patch).GetMethod("After");
			harmony.Patch(original, new HarmonyMethod(prefix), new HarmonyMethod(postfix));

			var b = new Test();

			Console.WriteLine("a=" + a.Call());
			Console.WriteLine("b=" + b.Call());
			Console.ReadKey();
		}
	}

	public class Test
	{
		// if Call() is too simple, it will get inlined and no patching is ever possible
		/*
		public string Call()
		{
			return "ORIGINAL";
		}*/

		public string Call()
		{
			var c = new char[] { 'O', 'R', 'I', 'G', 'I', 'N', 'A', 'L' };
			return string.Join("", c);
		}
	}

	public class Patch
	{
		public static bool Before(ref object __result)
		{
			Console.WriteLine("Before..");
			__result = "PATCHED";
			return false;
		}
		public static void After()
		{
			Console.WriteLine("After");
		}
	}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants