通过windbg看函数编译的位置排序

还是以下代码:

   class Program    {        static void Main(string[] args)        {            Console.WriteLine("WuLin ZhiZun BaoDao Tulong");            A a = new A();            a = null;            GC.Collect();
            Console.ReadLine();        }        public virtual void ABC()         {            Console.WriteLine("ABC ");        }        ~Program()        {                        Console.WriteLine("Kill A Program");        }    }

.

这段C#源码会被编译为IL,构成了四个方法,分别是静态方法Main,虚方法ABC,析构方法Finalize,以及默认构造函数.ctor。

通过WinDbg观察得到

00007FFE0304C770 00007ffe030f4948   NONE CoreCLR_CeShi.Program.Finalize()00007FFE03040098 00007ffe03010c08   NONE System.Object.ToString()00007FFE030400A0 00007ffe03010c18   NONE System.Object.Equals(System.Object)00007FFE030400B8 00007ffe03010c58   NONE System.Object.GetHashCode()00007FFE0304C768 00007ffe030f4938   NONE CoreCLR_CeShi.Program.ABC()00007FFE0304C778 00007ffe030f4968   NONE CoreCLR_CeShi.Program..ctor()00007FFE0304C760 00007ffe030f4920    JIT CoreCLR_CeShi.Program.Main(System.String[])

可以看到Finalize次序为1,Tostring为2,Equals为3,GetHashCode为4,虚方法ABC为5,默认构造.ctor为6

这个排序是怎么排的呢?

其实它是两轮排序:

第一次排序会过滤掉静态方法和非虚方法。那么Main和

.Ctor被排除掉了。虚方法ABC和Finalize(这个析构函数在编译为IL的时候也会被标记为虚方法)则会被处理。注意Finalize因为索引为1的位置已经有了,所以索引为1地方的Finalize会被当前类析构函数的Finalize所取代。

第二轮排序的时候,会首先查找默认构造函数和非默认构造函数,然后排序。最后查找上一轮没有被排序的也就是Main,放到排序次位的最后面。

结果也就是上面windbg展示的结果。索引从1到7.