sor*_*rin 10 c++ assert code-analysis visual-c++
Visual Studio /analyze为C/C++ 添加了代码分析(),以帮助识别错误的代码.这是一个非常好的功能,但是当您处理旧项目时,您可能会被警告的数量所淹没.
大多数问题都在产生,因为旧代码在方法或函数的开头做了一些ASSERT.
我认为这是代码中使用的ASSERT定义(来自afx.h)
#define ASSERT(f) DEBUG_ONLY((void) ((f) || !::AfxAssertFailedLine(THIS_FILE, __LINE__) || (AfxDebugBreak(), 0)))
Run Code Online (Sandbox Code Playgroud)
示例代码:
ASSERT(pBytes != NULL);
*pBytes = 0; // <- warning C6011: Dereferencing NULL pointer 'pBytes'
Run Code Online (Sandbox Code Playgroud)
我正在寻找一种简单,清洁和安全的解决方案来解决这些警告,这并不意味着禁用这些警告.我是否提到当前代码库中出现了很多事件?
/analyze不保证会产生相关和正确的警告.它可以并且将会遗漏很多问题,并且它也会产生许多误报(它被识别为警告,但它们非常安全且永远不会发生)
期望使用/ analyze进行零警告是不现实的.
它指出了一种情况,你取消引用它无法验证的指针始终有效.就PREfast而言,不能保证永远不会为NULL.
但这并不意味着它可以是NULL.只是证明它安全的分析对于PREfast来说过于复杂.
您可以使用特定于Microsoft的扩展__assume来告诉编译器它不应该产生此警告,但更好的解决方案是保留警告.每次使用/ analyze进行编译时(每次编译时都不需要),您应该验证它确实出现的警告仍然是误报.
如果您使用正确的断言(在编程时赶上逻辑错误,防范这情况不能发生,那么我看不出有什么问题,你的代码,或者离开的警告.添加代码来处理的问题可能永远不会发生仅仅是毫无意义的.你无缘无故地添加更多的代码和更多的复杂性(如果它永远不会发生,那么你无法从中恢复,因为你完全不知道程序将处于什么状态.你所知道的是它有它进入你认为不可能的代码路径.
但是,如果您将断言用作实际错误处理(在特殊情况下该值可能为NULL,您只是希望它不会发生),那么它就是代码中的缺陷.然后需要适当的错误处理(通常是例外).
永远不要使用断言来解决可能出现的问题.使用它们来验证不可能发生的事情.当/ analyze为您提供警告时,请查看它们.如果它是误报,请忽略它(不要压制它,因为虽然它今天是误报,但明天检查的代码可能会把它变成一个真正的问题).
PREFast 告诉您代码中存在缺陷;不要忽视它。事实上你确实有一个,但你只是匆匆地承认了这一点。问题是这样的:仅仅因为pBytes在开发和测试中从未为 NULL 并不意味着它不会投入生产。你不会处理这种可能性。PREfast 知道这一点,并试图警告您,生产环境是充满敌意的,并且会让您的代码变成一堆冒烟、残缺不全、毫无价值的字节。
/咆哮
有两种方法可以解决这个问题:正确的方法和黑客。
正确的方法是在运行时处理 NULL 指针:
void DoIt(char* pBytes)
{
assert(pBytes != NULL);
if( !pBytes )
return;
*pBytes = 0;
}
Run Code Online (Sandbox Code Playgroud)
这将使 PREfast 安静下来。
破解方法是使用注释。例如:
void DoIt(char* pBytes)
{
assert(pBytes != NULL);
__analysis_assume( pBytes );
*pBytes = 0;
}
Run Code Online (Sandbox Code Playgroud)
编辑: 这是描述 PREfast 注释的链接。无论如何,这是一个起点。
| 归档时间: |
|
| 查看次数: |
4021 次 |
| 最近记录: |