代码之家  ›  专栏  ›  技术社区  ›  R.Nosratabad

如何在静态代码分析器实用程序中查找NullReferenceException的潜在点?

  •  2
  • R.Nosratabad  · 技术社区  · 8 年前

    我们正在开发一个静态代码分析工具,旨在通过一些提示改进代码。

    我们希望找到开发人员忘记检查变量或属性或方法返回的可空性,并通过Dot Notation访问成员的地方,因为它可能会遇到NullReferenceException。

    例如,此代码:

    class Program
    {
        static void Main(string[] args)
        {
            var human = new Human();
            if (human.Name.Length > 10)
            {
                // Jeez! you have a long name;
            }
        }
    }
    
    public class Human
    {
        public string Name { get; set; }
    }
    

    class Program
    {
        static string name;
    
        static void Main(string[] args)
        {
            if (name.Length > 10)
            {
            }
        }
    }
    

    更新: 事实上,我们正在搜索表示 成员访问权限 对于IL中的给定变量。这可能吗?

    1 回复  |  直到 8 年前
        1
  •  3
  •   Jeroen Mostert    8 年前

    的文档 NullReferenceException 有助于记录以下内容:

    以下Microsoft中间语言(MSIL)说明 投 空引用异常 : callvirt , cpblk , cpobj , initblk , ldelem.<type> , ldelema , ldfld , ldflda , ldind.<type> , ldlen , stelem.<type> , stfld , stind.<type> , throw unbox .

    这些细分为以下内容:

    • 阵列访问: ldelem , 勒德莱马 , ldlen公司 , stelem 。数组引用不能是 null .
    • 非数组成员访问: 低密度流体力学 , ldflda公司 , stfld公司 。对象引用不能是 无效的 .
    • 方法访问: 卡尔维特 。对象引用不能是 无效的 属性访问也是方法访问,因为它调用属性getter/setter。
    • 指针/引用访问: cpblk公司 , cpobj公司 , 初始化blk , ldind , stind 。指针/引用不能是 无效的 。在经过验证的托管代码中,这些操作码通常不会在其参数可能 无效的 .
    • 引发异常: 。异常引用不能是 无效的 .
    • 拆箱 。对象引用不能是 无效的 .

    将操作码参数追溯回变量/字段是另一个问题。这可能会任意复杂,因为操作码只关心堆栈上的内容,而不关心它来自何处。在某些情况下,您可能需要处理表达式( a[0].SomeMethod().FieldAccess ,其中任何 a , a[0] a[0].SomeMethod() 可以是 无效的 当他们不应该是的时候)。

    Roslyn 为您提供语言水平的分析。获得高质量反馈信息的来源要简单得多。

    即使如此,也要意识到,对空性进行高质量的静态分析并不容易。您当然可以编写一个分析器,它会在程序员遇到任何可能的情况时发出警告 也许 忘记了检查,但是如果程序员被迫为引用插入大量多余的检查,那么这样的分析器几乎就没用了 从不 无效的 。如果您将此与TFS签入策略联系起来,请准备好接收来自开发人员和管理人员的死亡威胁,他们希望了解生产率下降的原因。

    像Resharper这样的现有工具添加了很多 attributes 用于控制分析,并且有一个 proposal 向上添加C#本身的可空性检查。在重新发明轮子之前,先了解自己的处境。

    推荐文章