通过代码静态工具检查看编码细节
来源:互联网 发布:证件照片裁剪软件 编辑:程序博客网 时间:2024/05/29 04:44
个人随笔 (Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)
近来做代码静态检视,发现除了比较严重的内存泄漏、逻辑错误等问题外,代码的细节、规范性问题很多。
静态工具检查出的点,经不起推敲,会发现代码逻辑中确实有许多不严谨的地方。
1. 在null 检查前解引用
如下面的例子:pT != nullptr判空前,已经有使用pT->a()了,判空就不起作用了,如果有异常,已经崩溃了。
class TestClass
{
int a;
int b;
};
TestClass* pT = getTestClass();
int c = pT->a();
…
if (pT != nullptr)
{
…
}
2. 在null 检查后解引用
如下面的例子:
pT != nullptr判空后做了某些处理;但在随后的处理中,再使用pT时,没有做判空处理。
在这种情况下,如果pT为空,就会崩溃在下面,判空处理的范围没有覆盖全。
TestClass* pT = getTestClass();
if (pT != nullptr)
{
…
}
int c = pT->a;
3. 显式 null 被解引用
这种不易察觉,在某个分支对元素赋值,另一分支未赋值,这种情况对于未赋值情况可能会出现崩溃。
如下面的例子:
TestClass* pT = nullptr;
if (y == 0)
{
pT = getTestClass();
}
int c = pT->a;
4. 逻辑死代码
有简单的,例如这种,最后一行无论如何走不进来:
if (xxx)
{
return 1;
}
else
{
return 0;
}
return 0;
逻辑上自相矛盾的地方,例如上面if包含的逻辑,else又做判定,如下面这种
if (pA == nullptr || pB == nullptr)
{
b = 1;
}
else
{
if (pB == nullptr)
{
do something
}
}
5. 未检查的 dynamic_cast
我们已知dynamic_cast对于类型是会做相应的检查,如果类型不在范围内的话,会返回false的,可是对于dynamic_cast,我们有时没有对返回的值做结果判定,这就有一定风险了;
例如:下面的show1,show2没有做dynamic_cast结果判定,当传入的值不是对应类型的时候,就会产生崩溃了。
class A
{};
class B : publice A
{void showB();};
class C: public A
{void showC();};
void show1(A* pA)
{
B* pB = dynamic_cast<B*>(pA);
pB->showB();
}
void show2(A* pA)
{
B* pC = dynamic_cast<C*>(pA);
pC->showC();
}
6. 混合了枚举类型
枚举类型,一般我们使用的时候,是各个对应各个的,但有时,因为值一样,我们可能就存在混用的情况。这个也是一种风险。
例如:getTypeA() 定义的返回是EnumTypeA,但判断时,使用了enumBDefault,虽然值是一样,但类型实际是不对应的,存在风险,万一哪天改了呢。
enum EnumTypeA
{
enumADefault = -1,
enumA1 = 0
};
enum EnumTypeB
{
enumBDefault = -1;
enumB1 = 0
};
EnumTypeA getTypeA()
{…}
if (getTypeA() == enumBDefault)
{
do something
}
7. 未初始化的标量字段
对于int/boo/指针/double等基本的数据类型,都是没有构造函数的,如果在struct/class中定义了,构造函数都需要赋值的,否则就会存在随机的情况。
例如下面的例子,getA函数,访问了TestClass p->a变量,a变量是有初值的,但是b变量是没有初值的,b的值实际上是随机的,这种情况就是一种潜在的风险。
我们无法确保所有的类似getA函数(当前不使用b)未来不会使用b变量作为参考。而且随机变量传递本身也是不建议出现的,好的做法是在class构造函数中,把基本数据类型变量都初始化了。
class TestClass
{
int a;
int b;
void * p
TestClass : p(nullptr), a(0){}
};
void getA(TestClass* p)
{
return p->a;
};
TestClass* pT = getTestClass();
int c = getA(pT);
8. 赋值而不是比较
从标题上就可以看出,问题比较清晰
例如:放入if语句的是一个赋值语句,这种一般都是写错了。
if (n = 0)
{
do something;
};
9. 常量表达式结果 (如 &&与||用错)
问题也比较清晰
例如:两处都是有问题的,第一处if判定恒true,第二处恒false
if (n != 0 || n != 1)
{
do something;
};
if (n == 0 && n == 1)
{
do something
}
10. 两侧相同
出现 if (pT != nullptr && pT != nullptr)这种情况,这种情况通常是想写别的。
如下面的例子:
if 中使用 pT1 != nullptr判断两次,但从上下文看,实际是也想判定pT2 != nullptr,这种情况是我们需要注意的。
TestClass* pT1 = getTestClass(xx);
TestClass* pT2 = getTestClass(yy);
if (pT1 != nullptr && pT1 != nullptr)
{
pT1 do something
pT2 do something
}
11. 适用于不同分支的相同代码
if与else的内容一致
例如:这种是if/else的处理一致,那还用if判定就没有意义了
if (a == 0)
{
b = 1;
}
else
{
b = 1;
}
个人随笔 (Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)
- 通过代码静态工具检查看编码细节
- 静态代码检查工具
- 静态代码检查工具-FindBugs
- 静态代码检查工具-PMD
- 静态代码检查工具 FindBugs
- Java静态代码检查工具
- 代码静态检查工具汇总
- Klocwork 静态代码检查工具
- 静态代码检查工具 FindBugs
- 静态代码检查工具 FindBugs
- 代码静态检查工具汇总
- 静态代码检查工具 FindBugs
- 静态代码检查工具 FindBugs
- 静态代码检查工具-PMD
- Lint 静态代码检查工具
- 静态代码检查工具 cppcheck
- 静态代码检查工具PC-Lint(一)
- 静态代码检查工具PC-Lint(一)
- 关于 win10 cpu 安装 anaconda navigator 打开闪退问题 解决方法
- Ie浏览器下检测插件是否已经安装
- leetcode 27. Remove Element
- 51nod 1218 最长递增子序列 V2 [dp]
- 123456
- 通过代码静态工具检查看编码细节
- WEB的基本概念
- JAVA JSONObjct.toBean() 转换为 JAVA Bean 时 JAVA Bean 带有 List 集合处理方案
- 架构师的问题
- 线程的建立 (基础)
- 二代交换更换Linux操作系统后调试注意事项
- Android Studio 虚拟机安装谷歌输入法
- [BZOJ]3140 二分图最大匹配
- head first设计模式cpp实现