调试空指针错误

思路大概是:

1. 获取exception的调用堆栈。

2. 获取exception相关的这个方法的方法的IL代码

3. 结合excpetion的IL偏移量和方法的IL,把调用源找出来。

代码
     class  Program
    {
        
static   void  Main( string [] args)
        {
            
try
            {
                
string  hello3  =   null ;

                hello3 
=  hello3.ToUpper();
            }
            
catch  (Exception ex)
            {
                
// 获取调用堆栈

                StackTrace trace 
=   new  StackTrace(ex,  true );

                StackFrame frame 
=  trace.GetFrame( 0 );

                
int  offset  =  frame.GetILOffset();

                
byte [] il  =  frame.GetMethod().GetMethodBody().GetILAsByteArray();


                
// 获取调用指令

                offset
++ ;

                
ushort  instruction  =  il[offset ++ ];


                
// 打开潘多拉魔盒

                ILGlobals 
global   =   new  ILGlobals();

                
global .LoadOpCodes();


                
// 翻译

                OpCode code 
=  OpCodes.Nop;

                
if  (instruction  !=   0xfe )
                {
                    code 
=   global .SingleByteOpCodes[( int )instruction];
                }
                
else
                {
                    instruction 
=  il[offset ++ ];
                    code 
=   global .MultiByteOpCodes[( int )instruction];
                    instruction 
=  ( ushort )(instruction  |   0xfe00 );
                }


                
// 获取方法信息

                
int  metadataToken  =  ReadInt32(il,  ref  offset);

                MethodBase callmethod 
=  frame.GetMethod().Module.ResolveMethod(metadataToken,
                     frame.GetMethod().DeclaringType.GetGenericArguments(),
                     frame.GetMethod().GetGenericArguments());

                
// 完成

                Console.WriteLine(callmethod.DeclaringType 
+   " . "   +  callmethod.Name);

                Console.Read();
            }

        }

        
private   static   int  ReadInt32( byte [] il,  ref   int  position)
        {
            
return  (((il[position ++ |  (il[position ++ <<   8 ))  |  (il[position ++ <<   0x10 ))  |  (il[position ++ <<   0x18 ));
        }

    }

    
public   class  ILGlobals
    {
        
private  OpCode[] multiByteOpCodes;

        
private  OpCode[] singleByteOpCodes;

        
///   <summary>
        
///  Loads the OpCodes for later use.
        
///   </summary>
         public   void  LoadOpCodes()
        {
            singleByteOpCodes 
=   new  OpCode[ 0x100 ];
            multiByteOpCodes 
=   new  OpCode[ 0x100 ];
            FieldInfo[] infoArray1 
=   typeof (OpCodes).GetFields();
            
for  ( int  num1  =   0 ; num1  <  infoArray1.Length; num1 ++ )
            {
                FieldInfo info1 
=  infoArray1[num1];
                
if  (info1.FieldType  ==   typeof (OpCode))
                {
                    OpCode code1 
=  (OpCode)info1.GetValue( null );
                    
ushort  num2  =  ( ushort )code1.Value;
                    
if  (num2  <   0x100 )
                    {
                        singleByteOpCodes[(
int )num2]  =  code1;
                    }
                    
else
                    {
                        
if  ((num2  &   0xff00 !=   0xfe00 )
                        {
                            
throw   new  Exception( " Invalid OpCode. " );
                        }
                        multiByteOpCodes[num2 
&   0xff =  code1;
                    }
                }
            }
        }

        
///   <summary>
        
///  Retrieve the friendly name of a type
        
///   </summary>
        
///   <param name="typeName">
        
///  The complete name to the type
        
///   </param>
        
///   <returns>
        
///  The simplified name of the type (i.e. "int" instead f System.Int32)
        
///   </returns>
         public   static   string  ProcessSpecialTypes( string  typeName)
        {
            
string  result  =  typeName;
            
switch  (typeName)
            {
                
case   " System.string " :
                
case   " System.String " :
                
case   " String " :
                    result 
=   " string " break ;
                
case   " System.Int32 " :
                
case   " Int " :
                
case   " Int32 " :
                    result 
=   " int " break ;
            }
            
return  result;
        }


        
public  OpCode[] MultiByteOpCodes
        {
            
get  {  return  multiByteOpCodes; }
        }

        
public  OpCode[] SingleByteOpCodes
        {
            
get  {  return  singleByteOpCodes; }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值