使用 Visual Studio 静态代码分析来分析应用商店应用的 C++ 代码质量

适用于 Windows 和 Windows Phone

Visual Studio Express 版本中的代码分析工具可检查代码中是否存在一组常见问题以及违反良好编程习惯的情况。 代码分析警告与编译器错误和警告不同,因为代码分析工具搜索的是虽然有效但仍会为你或使用你代码的其他人员带来问题的特定代码模式。 代码分析还可在代码中找到通过测试难以发现的缺陷。 在开发过程中定期运行代码分析工具可提高所编写的应用程序的质量。

备注

在 Visual Studio 旗舰版、Visual Studio 高级专业版和 Visual Studio 专业版中,可使用完整的代码分析工具。请参阅 MSDN 库中的使用代码分析工具来分析应用程序质量

在本主题中

可了解:

运行代码分析

分析和解决代码分析警告

禁止显示代码分析警告

搜索和筛选代码分析结果

C++ code analysis warnings

运行代码分析

若要对 Visual Studio 解决方案运行代码分析,请执行以下操作:

  • 在**“生成”菜单上,选择“对解决方案运行代码分析”**。

若要在每次生成项目时自动运行代码分析,请执行以下操作:

  1. 在解决方案资源管理器中选择项目名称,然后选择**“属性”**。

  2. 在项目属性页中,选择**“代码分析”,然后选择“生成时启用适用于 C/C++ 的代码分析”**。

这样,解决方案编译后将运行代码分析。 结果将显示在“代码分析”窗口中。

代码分析窗口

分析和解决代码分析警告

若要分析某个具体的警告,请在“代码分析”窗口中选择该警告的标题。 随后该警告将展开,显示有关问题的详细信息。 如果可能,代码分析将显示导致该警告的行号和分析逻辑。

展开的代码分析警告

展开警告后,将在 Visual Studio 代码编辑器中突出显示导致警告的代码行。

突出显示的源代码

了解问题后,可在代码中解决该问题。 然后,重新运行代码分析,以确保“代码分析”窗口中不再显示警告,并确保修复行为不会引发新的警告。

提示

可从“代码分析”窗口中重新运行代码分析。选择“分析”按钮,然后选择分析的范围。可对整个解决方案对所选项目重新运行分析。

禁止显示代码分析警告

有时,你可能会决定不修复代码分析警告。 你可能会觉得与代码的任何真实实现中引发问题的可能性相比,解决警告所需的重新编码工作量过大。 或者,你可能会认为在警告中使用的分析不适合特定的上下文。 可禁止显示个别警告,以使“代码分析”窗口中不再显示这些警告。

若要禁止显示警告,请执行以下操作:

  1. 如果未显示详细信息,可将警告的标题展开。

  2. 选择警告底部的**“操作”**链接。

  3. 选择**“禁止显示消息”,然后选择“在源中”**。

“禁止显示消息”插入 #pragma(warning:WarningId),它可禁止显示这行代码的警告。

搜索和筛选代码分析结果

可搜索冗长的警告消息列表,也可在多项目解决方案中筛选警告。

搜索并筛选代码分析窗口

C++ 代码分析警告

代码分析可引发以下有关 C++ 代码的警告:

规则

说明

C6001

使用未初始化的内存

C6011

取消引用 Null 指针

C6029

未选中的值的使用

C6053

来自调用的零终止

C6059

不正确的串联

C6063

缺少 Format 函数的字符串参数

C6064

缺少 Format 函数的整型参数

C6066

缺少 Format 函数的指针参数

C6067

缺少 Format 函数的字符串指针参数

C6101

返回未初始化的内存

C6200

索引超出最大缓冲区大小

C6201

索引超出最大堆栈缓冲区大小

C6270

缺少 Format 函数的浮点型参数

C6271

Format 函数的额外参数

C6272

Format 函数的非浮点型参数

C6273

Format 函数的非整型参数

C6274

Format 函数的非字符参数

C6276

无效字符串的强制转换

C6277

无效 CreateProcess 的调用

C6284

Format 函数的无效对象参数

C6290

逻辑非和按位与的优先级

C6291

逻辑非和按位或的优先级

C6302

Format 函数的无效字符串参数

C6303

Format 函数的无效宽字符串参数

C6305

不匹配的大小和计数的使用

C6306

不正确的变量参数函数的调用

C6328

可能的参数类型不匹配

C6385

读取溢出

C6386

写入溢出

C6387

无效的参数值

C6500

无效的特性属性

C6501

冲突的特性属性值

C6503

引用不能为 Null

C6504

在非指针参数中为 Null

C6505

对 Void 类型使用 MustCheck 属性

C6506

非指针参数或数组的缓冲区大小

C6507

取消引用零处的 Null 不匹配

C6508

常量缓冲区上的写入权限

C6509

返回使用的前置条件

C6510

在非指针参数中以 Null 结尾的参数

C6511

MustCheck 属性必须为 Yes 或 No

C6513

没有缓冲区大小的元素大小

C6514

缓冲区大小超过数组大小

C6515

非指针参数的缓冲区大小

C6516

在特性上无属性

C6517

有效的不可读缓冲区的大小

C6518

不可写的缓冲区的可写入大小

C6519

无效的批注:“NeedsRelease”属性的值必须为 Yes 或 No

C6521

取消引用无效大小的字符串

C6522

无效大小的字符串类型

C6523

无效大小的字符串参数

C6525

无效大小字符串的不可访问的位置

C6526

无效大小的字符串缓冲区类型

C6527

无效的批注:“NeedsRelease”属性可能不可用于 void 类型的值

C6530

无法识别的格式字符串样式

C6540

对该函数使用属性批注将使其现有的所有 __declspec 批注无效

C6551

大小规范无效:表达式不可分析

C6552

Deref= 或 Notref= 无效:表达式不可分析

C6701

该值不是有效的 Yes/No/Maybe 值

C6702

该值不是字符串值

C6703

该值不是一个数字

C6704

意外的批注表达式错误

C6705

批注参数的预期数量与批注参数的实际数量不匹配

C6706

批注的意外批注错误

C28021

批注的参数必须为指针型

C28182

取消引用 NULL 指针。 该指针包含与另一指针相同的 NULL 值。

C28202

非法引用非静态成员

C28203

对类成员的不明确的引用。

C28205

在非法上下文中使用的 _Success_ 或 _On_failure_

C28206

若左操作数指向结构,则使用“->”

C28207

若左操作数是一个结构,则使用“.”

C28210

__on_failure 上下文的批注不得位于显式的 pre 上下文中

C28211

SAL_context 所需的静态上下文名称

C28212

批注所需的指针表达式

C28213

_Use_decl_annotations_ 批注必须在不进行修改的情况下用于引用(在上一个声明中)。

C28214

特性参数的名称必须为 p1...p9

C28215

不能将 typefix 应用于已包含 typefix 的参数

C28216

checkReturn 批注仅应用于特定函数参数的后置条件。

C28217

对于函数,批注的参数数目与在文件中找到的数目不匹配

C28218

对于函数参数,批注的参数与在文件中找到的参数不匹配

C28219

批注中的批注参数所需的枚举成员

C28220

批注中的批注参数所需的整数表达式

C28221

批注中的参数所需的字符串表达式

C28222

批注所需的 __yes、__no 或 __maybe

C28223

未找到批注和参数所需的标记/标识符

C28224

批注需要参数

C28225

未在批注中找到所需参数的正确数目

C28226

批注也不能为 PrimOp(在当前声明中)

C28227

批注也不能为 PrimOp(请参阅上一个声明)

C28228

批注参数:在批注中不能使用类型

C28229

批注不支持参数

C28230

参数类型没有成员。

C28231

批注仅在数组上有效

C28232

pre、post 或 deref 不适用于任何批注

C28233

pre、post 或 dere 适用于块

C28234

__at 表达式不适用于当前函数

C28235

函数无法作为批注单独存在

C28236

批注无法在表达式中使用

C28237

不再支持参数上的批注

C28238

参数上的批注具有多个值:stringValue 和 longValue。 使用 paramn=xxx

C28239

参数上的批注包含两个值 stringValue 或 longValue;paramn=xxx。 仅使用 paramn=xxx

C28240

参数上的批注包含 param2,但不包含 param1

C28241

未识别参数上的函数的批注

C28243

参数上函数的批注需要的取消引用次数多于已批注的实际类型所允许的次数

C28245

函数的批注将在非成员函数上批注“this”

C28246

函数的参数批注与参数的类型不匹配

C28250

函数的批注不一致:上一实例发生错误。

C28251

函数的批注不一致:该实例发生错误。

C28252

函数的批注不一致:参数在此实例中包含另一个批注。

C28253

函数的批注不一致:参数在此实例中包含另一个批注。

C28254

批注中不支持 dynamic_cast<>()

C28262

对于批注,在函数中找到了批注的语法错误

C28263

在条件批注中找到内部批注的语法错误

C28264

结果列出了必须为常量的值。

C28267

在函数中找到了批注的语法错误。

C28272

在检查参数时,函数的批注与函数声明不一致

C28273

对于函数,线索与函数声明不一致

C28275

_Macro_value_ 参数为 null

C28279

对于符号,已找到“起始”符号,但没有匹配的“结束”符号

C28280

对于符号,已找到“结束”符号,但没有匹配的“起始”符号

C28282

格式字符串必须位于前置条件中

C28285

对于函数,参数中存在语法错误

C28286

对于函数,在其结尾附近出现语法错误

C28287

对于函数,_At_() 批注中出现语法错误(参数名无法识别)

C28288

对于函数,_At_() 批注中出现语法错误(参数名无法识别)

C28289

对于函数:ReadableTo 或 WritableTo 没有用作参数的限制规范

C28290

函数的批注包含的外部对象数量多于实际的参数数量

C28291

deref 级别 0 处的 post null/notnull 对于函数无意义。

C28300

运算符的不可兼容类型的表达式操作数

C28301

函数的第一个声明中不包含任何批注。

C28302

在批注上找到额外的 _Deref_ 运算符。

C28303

在批注上找到不明确的 _Deref_ 运算符。

C28304

找到应用于标记的错误放置的 _Notref_ 运算符。

C28305

在分析标记时发现错误。

C28350

批注介绍了无条件适用的情形。

C28351

批注介绍了在条件中无法使用动态值(变量)的位置。