C/C++/C++11软件测试实例
### C/C++/C++11软件测试实例 #### PVS-Studio静态代码分析工具介绍与应用案例 **PVS-Studio**是一款专为C/C++/C++11应用程序设计的静态代码分析工具,旨在帮助开发人员检测并修复源代码中的潜在错误。该工具通过三套不同的诊断规则来确保软件质量:64位错误诊断规则(Viva64)、平行错误诊断规则(VivaMP)以及通用诊断规则。 ### 示例:PVS-Studio检测出的典型错误 #### 1. **&和!操作的优先级** 在`ReturntoCastleWolfenstein`这款游戏中,PVS-Studio检测到了由于操作符优先级导致的问题: ```c++ #define SVF_CASTAI 0x00000010 if(!ent->r.svFlags&SVF_CASTAI) ``` 正确的写法应该是: ```c++ if(!(ent->r.svFlags&SVF_CASTAI)) ``` 这是因为`&`操作符的优先级高于`!`操作符,因此原始的代码等同于`!(ent->r.svFlags & SVF_CASTAI)`,这可能会导致逻辑错误。 #### 2. **&&代替&的用法** 另一个例子是在使用宏定义时出现的问题: ```c++ #define REO_INPLACEACTIVE (0x02000000L) #define REO_OPEN (0x04000000L) if(reObj.dwFlags&&REO_INPLACEACTIVE) m_pRichEditOle->InPlaceDeactivate(); if(reObj.dwFlags&&REO_OPEN) hr=reObj.poleobj->Close(OLECLOSE_NOSAVE); ``` 这里的问题在于应该使用`&`而不是`&&`来检查位标志。修改后的代码如下: ```c++ if(reObj.dwFlags & REO_INPLACEACTIVE) m_pRichEditOle->InPlaceDeactivate(); if(reObj.dwFlags & REO_OPEN) hr=reObj.poleobj->Close(OLECLOSE_NOSAVE); ``` #### 3. **数组auto_ptr的不正确使用** 在`Miranda IM`这款即时通讯软件中,PVS-Studio发现了以下问题: ```c++ auto_ptr<VARIANT> child_array(new VARIANT[child_count]); ~auto_ptr(){ delete _Myptr; } ``` 在这里,`auto_ptr`被错误地用于管理数组,导致析构函数只删除数组的第一个元素。为了避免这类问题,可以使用`boost::scoped_array`或`std::unique_ptr`。 #### 4. **条件总是正确的** 在`WinDjView`这款DjVu文件查看器中,有一个条件判断总是正确的错误: ```c++ inline bool IsValidChar(int c) { return c==0x9||0xA||c==0xD||c>=0x20&&c<=0xD7FF ||c>=0xE000&&c<=0xFFFD||c>=0x10000&&c<=0x10FFFF; } ``` 这段代码中的逻辑错误在于`||0xA`这一部分。因为`0xA`总是真值,所以整个表达式总是为真。修正后的代码应为: ```c++ inline bool IsValidChar(int c) { return c==0x9||c==0xA||c==0xD||c>=0x20&&c<=0xD7FF ||c>=0xE000&&c<=0xFFFD||c>=0x10000&&c<=0x10FFFF; } ``` #### 5. **代码格式不符合其本身的逻辑** 在一款未命名的软件中,发现了代码格式与逻辑不符的问题: ```c++ if(pushval!=0) if(pushval) v->GetUp(-1)=t; else v->Pop(1); ``` 这里的问题是第二个`if`语句可以简化为一个简单的条件分支,且`v->Pop(1);`永远不会被执行。修改后的代码如下: ```c++ if(pushval != 0) { if(pushval) v->GetUp(-1) = t; } else v->Pop(1); ``` #### 6. **声明附带的局部变量** 在`FCEUltra`这款任天堂娱乐系统模拟器中,PVS-Studio发现了一个声明局部变量的错误: ```c++ int iNesSaveAs(char *name) { fp = fopen(name, "wb"); int x = 0; if (!fp) int x = 1; } ``` 在这个例子中,变量`x`被重新声明了两次,这是不必要的。正确的做法是只声明一次并在需要的地方使用它: ```c++ int iNesSaveAs(char *name) { FILE *fp = fopen(name, "wb"); int x = 0; if (!fp) x = 1; } ``` #### 7. **将字符当初未定义的字符使用** 在某款软件中,出现了将字符作为未定义的字符使用的错误: ```c++ char *utf8CheckBuf = lineptr; while ((bUTF8) && (*utf8CheckBuf)) { if ((*utf8CheckBuf == 0xC0) || (*utf8CheckBuf == 0xC1) || (*utf8CheckBuf >= 0xF5)) { bUTF8 = false; break; } } ``` 这里的问题在于某些特定的字节值被视为非法的UTF-8序列。如果检测到这些值,则将文件视为ASCII编码。正确的代码应该检查所有可能的UTF-8序列。 #### 8. **附带使用的八进制值** 在`TortoiseSVN`这款Subversion版本控制系统的客户端中,出现了八进制值被错误使用的错误: ```c++ oCell._luminance = uint16(0.2220f * iPixel._red + 0.7067f * iPixel._blue + 0.0713f * iPixel._green); oCell._luminance = 2220 * iPixel._red + 7067 * iPixel._blue + 0713 * iPixel._green; ``` 在这个例子中,八进制值`0713`被错误地用于浮点运算。修正后的代码应该是使用十进制数: ```c++ oCell._luminance = 2220 * iPixel._red + 7067 * iPixel._blue + 713 * iPixel._green; ``` 以上这些示例展示了PVS-Studio如何有效地检测并帮助开发人员修复C/C++/C++11应用程序中的常见错误。通过使用这样的工具,可以显著提高代码质量和软件可靠性。
剩余35页未读,继续阅读
- 粉丝: 1
- 资源: 15
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助