这是一个简短的故事,说明如何使用PVS-Studio可以在PVS-Studio中使用的库的源代码中发现错误。 此外,不是理论上的,而是实际的-在分析仪中使用该库时,该错误在实践中得到了体现。
在PVS-Studio_Cmd(以及其他一些实用程序)中,我们使用特殊的库来解析命令行参数-CommandLine。
今天,我参与了在PVS-Studio_Cmd中支持新模式的工作,碰巧我不得不使用这个解析参数库。 在编写代码的过程中,我也正在调试它,因为我必须使用不熟悉的API。
因此,代码被编写,编译,运行以执行,ii ...
代码执行传递到
发生NullReferenceException类型的异常的库中。 从侧面看,这不是很清楚-我没有将任何显式的null引用传递给该方法。
以防万一,我看一下被调用方法的注释。 它们不太可能描述
NullReferenceException类型的异常的条件(因为在我看来通常是无法预料的,因为这种类型的异常是不可预见的)。
在对该方法的注释中,没有有关任何
NullReferenceException的信息(但是,这是预期的)。
为了查看导致异常的确切原因(在何处),我决定下载项目源代码,编译该库的调试版本并将其连接到分析器。 该项目的源代码
可在GitHub上找到 。 需要使用1.9.71版,因为正是分析仪现在使用的是这种类型。
我加载了适当版本的源代码,进行收集,将调试库连接到分析器,运行代码以进行执行,然后查看:
因此,异常的位置很明显
-helpInfo为
null ,这在访问
Left实例属性时会导致类型为
NullReferenceException的异常。
然后我变得体贴。 最近,用于C#的PVS-Studio在各个领域都得到了很好的改进,包括在搜索潜在的空引用的反引用方面。 特别是,改进了过程间分析。 因此,检查源代码以查看PVS-Studio是否可以找到正在讨论的错误对我来说立即变得很有趣。
我检查了源代码,在其他警告中,我确切地看到了我所希望的。
PVS-Studio警告 :
V3080在'helpInfo.Left'的方法中可能会取消引用。 考虑检查第二个参数:helpInfo。 解析器405
是的,那里! 正是您所需要的。 让我们更详细地看一下源代码。
private bool DoParseArgumentsVerbs( string[] args, object options, ref object verbInstance) { var verbs = ReflectionHelper.RetrievePropertyList<VerbOptionAttribute>(options); var helpInfo = ReflectionHelper.RetrieveMethod<HelpVerbOptionAttribute>(options); if (args.Length == 0) { if (helpInfo != null || _settings.HelpWriter != null) { DisplayHelpVerbText(options, helpInfo, null);
当调用
DisplayHelpVerbText方法时,分析器会生成警告消息,并警告第二个参数
-helpInfo 。 请注意,此方法位于
if语句的
then分支中。 条件表达式的构成方式使得可以使用以下变量值执行
then-分支:
- helpInfo == null ;
- _settings.HelpWriter!= null ;
让我们看一下
DisplayHelpVerbText方法的主体:
private void DisplayHelpVerbText( object options, Pair<MethodInfo, HelpVerbOptionAttribute> helpInfo, string verb) { string helpText; if (verb == null) { HelpVerbOptionAttribute.InvokeMethod(options, helpInfo, null, out helpText); } else { HelpVerbOptionAttribute.InvokeMethod(options, helpInfo, verb, out helpText); } if (_settings.HelpWriter != null) { _settings.HelpWriter.Write(helpText); } }
由于
动词== null (请参见方法调用),因此我们对
if语句的
then-分支感兴趣。 尽管
else分支的情况将类似,但我们将考虑
then分支,因为在我们的特殊情况下执行是通过它进行的。 请记住,
helpInfo可以为
null 。
现在,让我们看一下
HelpVerbOptionAttribute.InvokeMethod方法的主体。 实际上,您已经在上面的屏幕截图中看到了它:
internal static void InvokeMethod( object target, Pair<MethodInfo, HelpVerbOptionAttribute> helpInfo, string verb, out string text) { text = null; var method = helpInfo.Left; if (!CheckMethodSignature(method)) { throw new MemberAccessException( SR.MemberAccessException_BadSignatureForHelpVerbOptionAttribute .FormatInvariant(method.Name)); } text = (string)method.Invoke(target, new object[] { verb }); }
即使
helpInfo可以为
null ,也将无条件调用
helpInfo.Left 。 分析仪对此进行了警告,并发生了这种情况。
结论有趣的是,借助PVS-Studio,有可能在PVS-Studio中使用的库代码中发现错误。 我认为这是对“ PVS-Studio是否在PVS-Studio代码中发现错误?”问题的答案的一种延续。 :)它不仅可以在PVS-Studio代码中发现错误,而且可以在所用库的代码中发现错误。
最后,我建议
下载分析器并尝试检查您的项目-如果在那里也可以找到有趣的东西怎么办?

如果您想与讲英语的读者分享这篇文章,请使用以下链接:Sergey Vasiliev。
有关PVS-Studio如何在... PVS-Studio中使用的库中发现错误的故事