Different behavior of mirrored shared delegates with and without debugger

We came across some strange things, calling reflected general delegates. In some cases, with an attabched debuger we can make an impossible call, while without a debugger we cannot catch any exceptions and fastfails applications.

Here is the code:

using System;
using System.Windows.Forms;
using System.Reflection;

namespace GenericDelegate
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private delegate Class2 Delegate1();

        private void button1_Click(object sender, EventArgs e)
        {
            MethodInfo mi = typeof (Class1<>).GetMethod("GetClass", BindingFlags.NonPublic | BindingFlags.Static);
            if (mi != null)
            {
                Delegate1 del = (Delegate1) Delegate.CreateDelegate(typeof (Delegate1), mi);
                MessageBox.Show("1");
                try
                {
                    del();
                }
                catch (Exception)
                {
                    MessageBox.Show("No, I can`t catch it");
                }
                MessageBox.Show("2");
                mi.Invoke(null, new object[] {});//It Ok, we'll get exception here
                MessageBox.Show("3");
            }
        }


        class Class2
        {

        }


        class Class1<T> : Class2
        {
            internal static Class2 GetClass()
            {
                Type type = typeof(T);
                MessageBox.Show("Type name " + type.FullName +" Type: " + type + " Assembly " + type.Assembly);
                return new Class1<T>();
            }
        }
    }
}

There are two problems:

  • The behavior is different from the debugger and without
  • You cannot catch this error without a debugger using clr tricks. This is just no clr exception. There is a flag for accessing memory that reads the null pointer inside the internal code.

: . , . , , . VS ( .net 2.0 4.0) . . VS . , .

.net 4.0

, VS , ?

+3
4

, , . .NET 4.0, CreateDelegate() null. , JIT , , CreateDelegate null . FatalExecutionEngineError NRE, , 4.0

connect.microsoft.com. , , , , . , FEEE . , .

+2

, , , try/catch, , .

+1

VS 2008 VS .

static class Program
    {
        private delegate Foo Delegate1();
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            MethodInfo mi = typeof(Bar<>).GetMethod("GetClass", BindingFlags.NonPublic | BindingFlags.Static);
            if (mi != null)
            {
                var del = (Delegate1)Delegate.CreateDelegate(typeof(Delegate1), mi);

                MessageBox.Show("1");
                try
                {
                    del();
                    //mi.Invoke(null, BindingFlags.NonPublic | BindingFlags.Static, null, null,CultureInfo.InvariantCulture);
                }
                catch (Exception)
                {
                    MessageBox.Show("No, I can`t catch it");
                }
                MessageBox.Show("2");
                mi.Invoke(null, new object[] { });//It Ok, we'll get exception here
                MessageBox.Show("3");
            }
        }
        class Foo
        {

        }
        class Bar<T> : Foo
        {
            internal static Foo GetClass()
            {
                Type type = typeof(T);
                MessageBox.Show("Type name " + type.FullName + " Type: " + type + " Assembly " + type.Assembly);
                return new Bar<T>();
            }
        }
    }

del() uncomment mi.Invoke(),
.

GenericParameters

+1

I don’t think the code you posted really works under the .net framework vers. From 2.0 to 4.0. Static methods can be called AFAIK only on closed generic types, and not on open types. Therefore, you will have to specify a type parameter. As for the debugger, try starting the process outside of Visual Studio, and then attach the VS-Debugger. This time you will immediately receive the expected exception.

+1
source

Source: https://habr.com/ru/post/1745755/


All Articles