用 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 库中的使用代码分析工具分析应用程序质量。
在本主题中
可了解:
运行代码分析
若要对 Visual Studio 解决方案运行代码分析,请执行以下操作:
- 在**“生成”菜单上,选择“对解决方案运行代码分析”**。
若要在每次生成项目时自动运行代码分析,请执行以下操作:
在解决方案资源管理器中选择项目名称,然后选择**“属性”**。
在项目属性页中,选择**“代码分析”,然后选择“在生成时启用 C/C++ 的代码分析”**。
这样,解决方案编译后将运行代码分析。结果将显示在“代码分析”窗口中。
分析和解决代码分析警告
若要分析某个具体的警告,请在“代码分析”窗口中选择该警告的标题。随后该警告将展开,显示有关问题的详细信息。如有可能,代码分析将显示导致警告的行号和分析逻辑。
展开警告后,将在 Visual Studio 代码编辑器中突出显示导致警告的代码行。
了解问题后,可在代码中解决该问题。然后,重新运行代码分析,以确保“代码分析”窗口中不再显示警告,并确保修复行为不会引发新的警告。
提示
可从“代码分析”窗口中重新运行代码分析。选择“分析”按钮,然后选择分析的范围。可对整个解决方案对所选项目重新运行分析。
禁止显示代码分析警告
有时,您可能会决定不修复代码分析警告。您可能会觉得与代码的任何真实实现中引发问题的可能性相比,解决警告所需的重新编码工作量过大。或者,您可能会认为在警告中使用的分析不适合特定的上下文。可禁止显示个别警告,以使“代码分析”窗口中不再显示这些警告。
若要禁止显示警告,请执行以下操作:
如果未显示详细信息,则展开警告的标题。
选择警告底部的**“操作”**链接。
选择**“禁止显示消息”,然后选择“在源中”**。
禁止显示某个消息将插入 #pragma(warning:WarningId),它禁止对该行代码显示警告。
搜索和筛选代码分析结果
可搜索冗长的警告消息列表,也可在多项目解决方案中筛选警告。
C++ 代码分析警告
代码分析对 C++ 代码引发以下警告:
规则 |
说明 |
---|---|
正在使用未初始化的内存 |
|
正在取消对 NULL 指针的引用 |
|
使用未经检查的值 |
|
调用中包含零终止 |
|
错误串联 |
|
格式函数缺少字符串参数 |
|
格式函数缺少整数参数 |
|
格式函数缺少指针参数 |
|
格式函数缺少字符串指针参数 |
|
返回未初始化的内存 |
|
索引超出缓冲区最大容量 |
|
索引超出堆栈缓冲区最大容量 |
|
格式函数缺少浮点参数 |
|
格式函数有多余参数 |
|
格式函数有非浮点参数 |
|
格式函数有非整数参数 |
|
格式函数有非字符参数 |
|
字符串强制转换无效 |
|
CreateProcess 调用无效 |
|
格式函数的对象参数无效 |
|
逻辑非按位与优先顺序 |
|
逻辑非按位或优先顺序 |
|
格式函数的字符字符串参数无效 |
|
格式函数的宽字符字符串参数无效 |
|
大小和计数使用不匹配 |
|
变量参数函数调用错误 |
|
潜在参数类型不匹配 |
|
读溢出 |
|
写溢出 |
|
参数值无效 |
|
无效特性属性 |
|
特性属性值冲突 |
|
引用不可为 Null |
|
非指针为 Null |
|
Void 的 MustCheck |
|
非指针或数组的缓冲区大小 |
|
取消引用零处的 Null 不匹配 |
|
常量写访问 |
|
对前置条件使用了返回值 |
|
Null 终止于非指针 |
|
MustCheck 必须为 Yes 或 No |
|
无缓冲区大小的元素大小 |
|
缓冲区大小超出数组大小 |
|
非指针缓冲区大小 |
|
特性无属性 |
|
不可读缓冲区的有效大小 |
|
不可写缓冲区的可写大小 |
|
无效的批注:“NeedsRelease”属性的值必须为 Yes 或 No |
|
无效大小字符串取消引用 |
|
无效大小字符串类型 |
|
无效大小字符串参数 |
|
无效大小字符串不可访问位置 |
|
无效大小字符串缓冲区类型 |
|
无效的批注: 无法对 void 类型的值使用“NeedsRelease”属性 |
|
无法识别的格式字符串样式 |
|
对此函数使用特性批注将使其现有的所有 __declspec 批注无效 |
|
大小规格无效: 无法分析表达式 |
|
无效的 Deref= 或 Notref=: 无法分析表达式 |
|
该值不是有效的 Yes/No/Maybe 值:“%1$ls” |
|
该值不是字符串值 |
|
该值不是数字 |
|
意外的批注表达式错误 |
|
批注的预期参数数量与批注的实际参数数量不匹配 |
|
以下批注的意外批注错误 |
|
所批注的参数必须是指针 |
|
正在取消对 NULL 指针的引用。指针包含与其他指针相同的 NULL 值。 |
|
对非静态成员进行了非法引用 |
|
对类成员进行了不明确的引用。 |
|
在非法上下文中使用了 _Success_ 或 _On_failure_ |
|
当左操作数指向一个结构时,请使用“->” |
|
左操作数是一个结构,请使用“.” |
|
__on_failure 上下文的批注不得位于显式的 pre 上下文中 |
|
SAL_context 需要静态上下文名称 |
|
批注需要指针表达式 |
|
_Use_decl_annotations_ 批注必须用于引用(无需修改)以前的声明。 |
|
特性参数名称必须为 p1 至 p9 |
|
typefix 无法应用于已具有 typefix 的参数 |
|
checkReturn 批注仅适用于特定函数参数的后置条件。 |
|
对于函数,批注的参数数量与在文件中找到的数量不匹配 |
|
对于函数参数,批注的参数与在文件中找到的参数不匹配 |
|
批注中的参数应为枚举成员 |
|
批注中的参数应为整数表达式 |
|
批注中的参数应为字符串表达式 |
|
批注应使用 __yes、__no 或 __maybe |
|
对于批注,参数未找到预期的标记/标识符 |
|
批注需要参数 |
|
在批注中找到的所需参数的数量不正确 |
|
批注也不能为 PrimOp (在当前声明中) |
|
批注也不能为 PrimOp (参见上一个声明) |
|
批注参数: 不能在批注中使用类型 |
|
批注不支持参数 |
|
参数类型没有成员。 |
|
批注仅对数组有效 |
|
pre、post 或 deref 未应用于任何批注 |
|
pre、post 或 deref 应用于块 |
|
__at 表达式不适用于当前函数 |
|
函数不能作为批注单独存在 |
|
不能在表达式中使用该批注 |
|
不再支持参数上的批注 |
|
参数上的批注有多个 value、stringValue 和 longValue。使用 paramn=xxx |
|
参数上的批注同时具有 value、stringValue 或 longValue 之一和 paramn=xxx。仅使用 paramn=xxx |
|
参数上的批注有 param2,但没有 param1 |
|
无法识别参数上函数的批注 |
|
参数上函数的批注需要的取消引用次数多于已批注的实际类型所允许的次数 |
|
函数的批注在非成员函数上批注“this” |
|
参数函数的批注与参数的类型不匹配 |
|
函数的批注不一致: 上一个实例有错误。 |
|
函数的批注不一致: 此实例有错误。 |
|
函数的批注不一致: 参数在此实例上有另一个批注。 |
|
函数的批注不一致: 参数在此实例上有另一个批注。 |
|
批注中不支持 dynamic_cast<>() |
|
函数的批注中发现了批注语法错误 |
|
内部批注的条件批注中发现了语法错误 |
|
结果列表值必须是常量。 |
|
函数的批注中发现了批注语法错误。 |
|
检查时针对函数参数的批注与函数声明不一致 |
|
对于函数,线索与函数声明不一致 |
|
_Macro_value_ 的参数为 null |
|
对于符号,已找到“begin”,但没有匹配的“end” |
|
对于符号,已找到“end”,但没有匹配的“begin” |
|
格式字符串必须位于前置条件中 |
|
对于函数,参数中有语法错误 |
|
对于函数,结尾附近有语法错误 |
|
对于函数,_At_() 批注中存在语法错误(无法识别的参数名) |
|
对于函数,_At_() 批注中存在语法错误(参数名无效) |
|
对于函数: ReadableTo 或 WritableTo 没有用作参数的限制规范 |
|
函数的批注包含的外部对象多于参数的实际数量 |
|
deref 级别 0 处的 post null/notnull 对于函数无意义。 |
|
表达式操作数的类型与运算符不兼容 |
|
函数的第一个声明没有批注。 |
|
批注上发现了 extra _Deref_ 运算符。 |
|
批注上发现了不明确的 _Deref_ 运算符。 |
|
发现向标记应用的 _Notref_ 运算符的位置不正确。 |
|
分析标记时发现了错误。 |
|
批注描述的情况并非有条件地适用。 |
|
批注所描述的情况下不能使用动态值(变量)。 |