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