向所有错误爱好者致以问候。 新年快到了,因此该是对即将到来的一年进行评估的时候了。 按照传统,对PVS-Studio团队在2019年开放C#项目中发现的最有趣的错误进行评级。 准备好了吗 然后开始吧。
第十名:“让所有人困惑”
V3066传递给“ AdjustCellBorderStyle”方法的参数的可能错误顺序:“ isFirstDisplayedRow”和“ isFirstDisplayedColumn”。 DataGridViewComboBoxCell.cs 1934
protected override void OnMouseMove(DataGridViewCellMouseEventArgs e) { .... dgvabsEffective = AdjustCellBorderStyle( DataGridView.AdvancedCellBorderStyle, dgvabsPlaceholder, singleVerticalBorderAdded, singleHorizontalBorderAdded, isFirstDisplayedRow,
文章“
WinForms:错误,Holmes ”中的
错误 。 分析器指出,当将参数传递给方法时,最后两个参数被反转。 让我们看一下
AdjustCellBorderStyle声明 :
public virtual DataGridViewAdvancedBorderStyle AdjustCellBorderStyle( DataGridViewAdvancedBorderStyledataGridViewAdvancedBorderStyleInput, DataGridViewAdvancedBorderStyle dataGridViewAdvancedBorderStylePlaceholder, bool singleVerticalBorderAdded, bool singleHorizontalBorderAdded, bool isFirstDisplayedColumn, bool isFirstDisplayedRow) { .... }
看来分析仪是正确的。 通常,某些参数是故意以相反的顺序传递的,例如为了交换某些变量。 但是看起来情况并非如此。 首先,
布尔类型变量令人困惑。 其次,方法的名称也很常见:没有“交换”或“反向”。 此外,犯这样的错误并不难:人们通常对行/列对的顺序有不同的认识。
第九名:“无限临近”
V3110'TryValidateModel '方法内可能进行的无限递归。 PrefixedModuleUpdater.cs 48
public bool TryValidateModel(object model, string prefix) { return TryValidateModel(model, Prefix(prefix)); }
文章“
在Orchard CMS代码中搜索和分析错误”中的错误 。 犯了一个错误,该错误导致无限递归。 要了解如何发生此错误,您需要查看
TryValidateModel方法的重载:
public bool TryValidateModel(object model) { return _updateModel.TryValidateModel(model); }
在第一种情况下,可能需要使用以下形式的调用:
public bool TryValidateModel(object model, string prefix) { return _updateModel.TryValidateModel(model, Prefix(prefix)); }
因为
_updateModel类型为
IUpdateModel ,所以已编译的代码,并且当前类还实现了
IUpdateModel接口。
第八名:“尝试,找到”
V3091实证分析。 字符串文字中可能存在拼写错误:“管理组ID”。 “ Id”一词可疑。 Constants.cs 36
public class HelpMessages { public const string SubscriptionId = "Subscription Id of the subscription associated with the management"; public const string GroupId = "Management Group Id";
该错误来自“
Azure PowerShell:”基本无害 。”分析人员怀疑
GroupName常量已使用错误字符串初始化。可能应该出现类似
“ Management Group Name”的字样 。很难判断此错误的严重性,但这种情况非常罕见,并且很难发现。
第七名:“只是被忽略”
V3078重复调用'OrderBy'方法后,原始排序顺序将丢失。 使用“ ThenBy”方法保留原始排序。 GridModel.Selection.cs 107
internal partial class GridModel { private void BuildCellSelectionRegions(....) { .... this.MergeCellSelectionRegions(selectedItemsInView .OrderBy(c => c.Column.ItemInfo.LayoutInfo.Line) .OrderBy(c => c.RowItemInfo.LayoutInfo.Line)); } }
文章“
检查Telerik UI以使UWP熟悉PVS-Studio ”中的错误。 由于对已排序的集合重用了
OrderBy ,因此先前排序的结果将丢失。 您必须使用
ThenBy :
this.MergeCellSelectionRegions(selectedItemsInView .OrderBy(c => c.Column.ItemInfo.LayoutInfo.Line) .ThenBy(c => c.RowItemInfo.LayoutInfo.Line));
这些错误是由于粗心或无知造成的。 我认为应该归咎于复制粘贴。
第六名:“代码已记录在案,”他们说
V3009这种方法总是返回一个相同的'true'值,这很奇怪。 MaskedTextProvider.cs 1529
public bool Remove(out int testPosition, out MaskedTextResultHint resultHint) { .... if (lastAssignedPos == INVALID_INDEX) { .... return true;
文章“
使用PVS-Studio静态分析器验证.NET Core库的源代码 ”中的错误。 该方法将始终返回
true 。 是的,这是一个错误,但是还有其他事情很好奇。 该方法附有详细的注释:
从格式化的字符串中删除最后一个字符。 (删除虚拟字符串中的最后一个字符)。 退出时,out参数包含实际执行操作的位置。 此位置相对于测试字符串。 MaskedTextResultHint输出参数可提供有关操作结果的更多信息。 成功 返回 true , 否则 返回 false 。专注于最后一句话。 但是谁读过这些评论? 但是严重的是,例如在重构或调试时,这种错误很容易蔓延。 当方法的结果始终为
true时 ,我们想检查该选项,那么,我们忘记了返回所有内容。
第五名:“立即索引我!”
V3102通过循环内的常量索引可疑访问“ seq”对象的元素。 XmlQueryRuntime.cs 738
public bool MatchesXmlType(IList<XPathItem> seq, ....) { .... for (int i = 0; i < seq.Count; i++) { if (!CreateXmlType(seq[0]).IsSubtypeOf(....)) return false; } return true; }
文章“
使用PVS-Studio静态分析器验证.NET Core库的源代码 ”中的错误。 在遍历
seq集合时,
for循环在所有迭代中错误地仅使用对其第一个元素的访问(索引0而不是
i )。
第四名:“仅仅一美元,还不够”
V3138字符串文字包含潜在的内插表达式。 考虑检查:e。 SSPIHandleCache.cs 42
internal static void CacheCredential(SafeFreeCredentials newHandle) { try { .... } catch (Exception e) { if (!ExceptionCheck.IsFatal(e)) { NetEventSource.Fail(null, "Attempted to throw: {e}"); } } }
文章“
使用PVS-Studio静态分析器验证.NET Core库的源代码 ”中的错误。
似乎插入了字符串
“尝试抛出:{e}” 。 由于缺少
$字符,因此
e异常的字符串表示形式不会替换为该字符串。 结果,该字符串将“按原样”使用。
第三名:“没有出路”
V3008 [CWE-563]连续两次为“ this.linker.s3.region”变量分配值。 也许这是一个错误。 检查行:116,114。AWSSDK.DynamoDBv2.Net45 S3Link.cs 116
public string Region { get { .... } set { if (String.IsNullOrEmpty(value)) { this.linker.s3.region = "us-east-1"; } this.linker.s3.region = value; } }
文章“
寻找适用于.NET的Amazon Web Services SDK的源代码中的错误 ”
中的错误 。 在
if块的主体中,
return被跳过。 结果,
this.linker.s3.region变量
将始终获取
值 ,包括空字符串和
null 。
第二名:“变得有秩序!”
V3070在初始化“ LOCALE_USER_DEFAULT”变量时使用未初始化的变量“ LANG_USER_DEFAULT”。 NativeMethods.cs 890
internal static class NativeMethods { .... public static readonly int LOCALE_USER_DEFAULT = MAKELCID(LANG_USER_DEFAULT); public static readonly int LANG_USER_DEFAULT = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT); .... }
文章“
WinForms:错误,Holmes ”中的
错误 。 类字段的初始化顺序混合在一起。 要计算
LOCALE_USER_DEFAULT字段的值,请使用
LANG_USER_DEFAULT字段,该字段尚未初始化且值为0。代码中的其他任何地方均未使用
LANG_USER_DEFAULT变量。 为了理解此错误导致的原因,编写了一个测试程序,其中包含WinForms代码中的方法。 为简单起见,一些实际常量被替换为其实际值:
internal static class NativeMethods { public static readonly int LOCALE_USER_DEFAULT = MAKELCID(LANG_USER_DEFAULT); public static readonly int LANG_USER_DEFAULT = MAKELANGID(0x00, 0x01); public static int MAKELANGID(int primary, int sub) { return ((((ushort)(sub)) << 10) | (ushort)(primary)); } public static int MAKELCID(int lgid) { return MAKELCID(lgid, 0x0); } public static int MAKELCID(int lgid, int sort) { return ((0xFFFF & lgid) | (((0x000f) & sort) << 16)); } } class Program { static void Main() { System.Console.WriteLine(NativeMethods.LOCALE_USER_DEFAULT); } }
启动后,控制台上将显示以下内容:0。现在,我们将通过交换
LOCALE_USER_DEFAULT和
LANG_USER_DEFAULT字段的声明来更正错误。 程序的结果格式如下:1024。
第一名:“信任,但要验证”
与第一名总是很难的。 必须有一些非同寻常且非常有趣的东西。 最初,我为本文选择了20多个有趣的错误,但其中没有什么值得一提的。 然后我想起了我的同事谢尔盖·瓦西里耶夫(Sergey Vasiliev)的一篇文章,该文章致力于一个错误。 该错误的妙处在于它直接影响了我们分析仪的运行。 怎么了 从文章“
PVS-Studio如何在... PVS-Studio中使用的库中发现错误的历史 ”的标题中已经很清楚了。 同样,懒惰并没有被消除。 :)在这里,我完全感到as愧,将不对错误进行描述,但建议您按照本文的链接查找更多信息。 我保证-值得。 而且文章简短。
结论
我希望这些错误是有趣的,但是这篇文章并不累。 提醒您,您随时可以
下载 PVS-Studio分析仪,以自己和第三方项目搜索错误,以取悦自己,朋友和同事。 让错误更少,更多时间自我完善! :)
你看过吗 恭喜您迈上了新的台阶! 在我们博客的以下文章中,重点介绍了2019年
Java和
C ++项目
中的最佳bug。

如果您想与讲英语的读者分享这篇文章,请使用以下链接:Sergey Khrenov。
2019年在C#项目中发现的十大错误