用 Visual Studio 代码分析来分析 Windows 应用商店应用程序的 C++ 代码质量

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

备注

在 Visual Studio Ultimate 2012、Visual Studio Premium 2012 和 Visual Studio Professional 2012 中,可使用完整的代码分析功能。请参见 MSDN 库中的使用代码分析工具分析应用程序质量

在本主题中

可了解:

运行代码分析

分析和解决代码分析警告

禁止显示代码分析警告

搜索和筛选代码分析结果

C++ 代码分析警告

运行代码分析

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

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

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

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

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

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

“代码分析”窗口

分析和解决代码分析警告

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

展开的代码分析警告

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

突出显示的源代码

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

提示

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

禁止显示代码分析警告

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

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

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

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

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

禁止显示某个消息将插入 #pragma(warning:WarningId),它禁止对该行代码显示警告。

搜索和筛选代码分析结果

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

“搜索并筛选代码分析”窗口

C++ 代码分析警告

代码分析对 C++ 代码引发以下警告:

规则

说明

C6001

正在使用未初始化的内存

C6011

正在取消对 NULL 指针的引用

C6029

使用未经检查的值

C6053

调用中包含零终止

C6059

错误串联

C6063

格式函数缺少字符串参数

C6064

格式函数缺少整数参数

C6066

格式函数缺少指针参数

C6067

格式函数缺少字符串指针参数

C6101

返回未初始化的内存

C6200

索引超出缓冲区最大容量

C6201

索引超出堆栈缓冲区最大容量

C6270

格式函数缺少浮点参数

C6271

格式函数有多余参数

C6272

格式函数有非浮点参数

C6273

格式函数有非整数参数

C6274

格式函数有非字符参数

C6276

字符串强制转换无效

C6277

CreateProcess 调用无效

C6284

格式函数的对象参数无效

C6290

逻辑非按位与优先顺序

C6291

逻辑非按位或优先顺序

C6302

格式函数的字符字符串参数无效

C6303

格式函数的宽字符字符串参数无效

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

无效的批注: 无法对 void 类型的值使用“NeedsRelease”属性

C6530

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

C6540

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

C6551

大小规格无效: 无法分析表达式

C6552

无效的 Deref= 或 Notref=: 无法分析表达式

C6701

该值不是有效的 Yes/No/Maybe 值:“%1$ls”

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 或 deref 应用于块

C28234

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

C28235

函数不能作为批注单独存在

C28236

不能在表达式中使用该批注

C28237

不再支持参数上的批注

C28238

参数上的批注有多个 value、stringValue 和 longValue。使用 paramn=xxx

C28239

参数上的批注同时具有 value、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

对于符号,已找到“begin”,但没有匹配的“end”

C28280

对于符号,已找到“end”,但没有匹配的“begin”

C28282

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

C28285

对于函数,参数中有语法错误

C28286

对于函数,结尾附近有语法错误

C28287

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

C28288

对于函数,_At_() 批注中存在语法错误(参数名无效)

C28289

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

C28290

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

C28291

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

C28300

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

C28301

函数的第一个声明没有批注。

C28302

批注上发现了 extra _Deref_ 运算符。

C28303

批注上发现了不明确的 _Deref_ 运算符。

C28304

发现向标记应用的 _Notref_ 运算符的位置不正确。

C28305

分析标记时发现了错误。

C28350

批注描述的情况并非有条件地适用。

C28351

批注所描述的情况下不能使用动态值(变量)。