【实用工具】代码检测

151 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第9天,点击查看活动详情

代码检测

静态检测 cppcheck

  • 工具:cppcheck

  • 安装:sudo apt install cppcheck

  • 使用: 具体使用可以参考cppcheck -h,以及官方手册

         # 目录
         unitest/src
         ├── CMakeLists.txt
         ├── ref.cpp
         ├── sizeof_.cc  # 正常
         └── string_.cpp # 有内存泄漏
    
    • 检测指定的文件:cppcheck string_.cpp

       unitest/src$ cppcheck string_.cpp
           Checking string_.cpp ...
           [string_.cpp:12]: (error) Memory leak: pt 
       # 12行:错误类型为error,错误信息是:Memory leak,变量pt
       ​
       unitest/src$ cppcheck sizeof_.cc 
           Checking sizeof_.cc ...
      
    • 检测指定的目录:cppcheck src

       unitest$ cppcheck src
           Checking src/ref.cpp ...
           1/3 files checked 33% done
           Checking src/sizeof_.cc ...
           2/3 files checked 66% done
           Checking src/string_.cpp ...
           [src/string_.cpp:12]: (error) Memory leak: pt # 检测出来
           3/3 files checked 100% done
      
    • 不检测指定某个文件或者目录:加上参数 -i。如果屏蔽多个文件,每个前面都要加 -i

       # 不检测src/下的`sizeof_.cc`文件
       unitest$ cppcheck -i src/sizeof_.cc src
           Checking src/ref.cpp ...
           1/2 files checked 50% done
           Checking src/string_.cpp ...
           [src/string_.cpp:12]: (error) Memory leak: pt
           2/2 files checked 100% done
      
    • 严重性质等级 cppcheck --enable=<id> file,具体使用可以参考:cppcheck -h

      • error:在发现 bug 时候使用
      • warning:阻止bug的建议
      • stylestylistic issues related to code cleanup
      • performance:对于代码性能的建议。
      • portability:可移植性问题。代码在32/64位不同的平台上可能不能工作。
      • information:配置问题。仅在配置时候使用
    • 将检测结果输入到文件中 使用shell的管道重定向:

           cppcheck  string_.cpp --quiet  2> checkInfo.txt 
           # --quiet 是为了不在控制台打印
           # 2>checkInfo.txt 实现将错误信息重定向到checkInfo.txt
      
    • 配合CMake

      • CMakebuild目录下使用:cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON . 这样会自动在该目录下生成compile_commands.json
      • 然后在运行:cppcheck --project=compile_commands.json。 也可以将错误信息重定向到输出文件: cppcheck --project=compile_commands.json 2>checkInfo.txt

动态检测 valgrind

  • 安装:sudo apt install valgrind

  • --tool=<name>

    • name=Memcheck:默认工具。 主要是针对内存进行检测,比如:未初始化的内存、使用已经释放的内存、内存访问越界等。
    • name=Callgrind:检查程序中函数调用过程中的问题。
    • name=Cachegrind:检查程序中缓存使用出现的问题。
    • name=Helgrind:用来检查多线程程序中出现的竞争问题
    • name=Massif:检查程序中堆栈使用中的问题。
    • Extension:利用core提供的功能,自己编写特定的内存调试工具。

为了使valgrind发现的错误更精确,如能够定位到源代码行,建议在编译时加上 -g 参数,编译优化选项请选择O0,虽然这会降低程序的执行效率,也可以使用CMake产生可执行文件。

  • new的内存进行delete

     // valgrind_1.cc
         #include<iostream>
     ​
         void fun() {
             int* ptr = new int[10];
             ptr[0] = 10;
             return ;
         }
     ​
         int main(int argc, char const *argv[]) {
             fun();
             return 0;
         }
     ​
    

    运行valgrind --log-file=checkInfo.txt --leak-check=full ./valgrind_1

    • --log-file=checkInfo.txt: 将输出信息重定向到文件中
    • --leak-check=full:显示详细的错误 其他参数参考valgrind -h

最好配合cppcheck一起使用,有些问题可能valgrind因为编译器的问题检测不出。比如:使用未初始化的内存

     int main(int argc, char const *argv[]) {
         int a[4];
         int i, s;
         a[0] = a[1] = 0;
         for(int i=0; i<4; i++)
             s += a[i];
         return 0;
     }

可能由于编译器的版本不同,valgrind工具没有检测出使用未初始化的内存问题,但是cppcheck检出。

 src$ cppcheck valgrind_2.cc 
 Checking valgrind_2.cc ...
 [valgrind_2.cc:8]: (error) Uninitialized variable: s