C/C++代码静态检测工具PC-Lint常见错误总结

news2024/11/20 23:18:55

目录

1、PC-Lint 概述

2、PC-lint 常见错误列举

3、PC-Lint报告的语法错误

4、总结


VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931C++软件分析工具从入门到精通案例集锦(专栏文章正在更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131405795C/C++基础与进阶(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.html       为了提高代码质量,我们一般会引入一些代码静态检测工具,比如PC-lint和腾讯的TScanCode等,可以帮我们发现代码中存在的一些潜在问题。之前我们项目中使用了PC-Lint,本文大概地总结一个PC-Lint的常报错误,以及这些错误的解决办法。

1、PC-Lint 概述

       PC-Lint是一种C/C++静态代码检测工具,通过扫描静态的代码文件(头文件和源文件)进行分析,不仅可以像IDE编译器那样检查出一般的语法错误,还可以检查出那些表面上完全合乎语法要求,但很可能是潜在的、不易发现的问题或错误,比如数组访问越界、内存泄漏、使用未初始化变量等,这样就可以很好地提高软件的质量。

       对于这些bug,如果事先没有检测,在软件运行过程中出了问题,通过走读代码或者使用分析工具去分析,可能会花费很长时间才能找到原因。通过使用PC-Lint进行检测,可以在测试开始前就能检测出这些错误,会给测试和开发节省很多的时间。虽然使用PC-Lint会花费一些时间,但这是完全值得的。

       另外,PC-lint还支持Effective C++ / More Effective C++中说描述的各种提高效率和防止错误的方法,对照相应的条款,还可以学习与熟悉这些编程要点,提升我们编码的技能。

2、PC-lint 常见错误列举

       下面所列举的常见错误只有ID号与简单的描述信息,如果有需要,可以通过ID号在PC-Lint目录下的MsgRef.html文件中查看详细的描述信息。另外本文对这些错误只进行了一些简单的分析,其中部分错误可以参见《Effective C++》上相应的条款。

1)error 1561: (Warning -- Reference initialization causes loss of const/volatile integrity (arg. no. 1))

        PC-Lint发出警告:“第一个参数在初始化时会破坏const属性”,双击警告,定位到代码:

TManufacturerInfo *pManufactureList=NULL;
DWORD dwManufactureNum=g_pcCommData->GetAllManufactory(pManufactureList);

查看一下GetAllManufactory函数的声明:

DWORD GetAllManufactory(const TManufacturerInfo*& ptManufactory) const;

参数是const TManufacturerInfo*&,不希望指针所指向的内容被改变,但是我们传入的参数是TManufacturerInfo *,缺少了const限制,导致我们就可以随意改变指针所指向的内容。 

2)error 1401: (Warning -- member ‘XXX::YYY' not initialized by constructor);

        成员变量没有被初始化,会造成程序一些不可预知的结果,对于这些危害,大家都比较清楚的,但这还是最常犯的一些错误之一,因为大家在开始写代码的时候或以后的维护的时候还会忘记的。

3)error 1729: (Initializer inversion detected for member 'Symbol' );

       成员变量在初始化列表的顺序与在类声明中出现的顺序不一致。C++总是按成员变量在类声明中出现的顺序来初始化成员变量的,如果不一致有可能造成一些隐蔽的bug;例如下面的代码:

class A
{
public:
    A( ):y(100),x(y)
    {
    }
private:
    int x;
    int y;
};

在成员变量初始化时,由于y(100)写在了x(y)之前,我们很可能认为先执行y(100),然后执行x(y),这样x与y的值都初始化为100,但实际上x(y)首先执行,y这时还没有被初始化,x就被初始化为一个随机值。

4)error 1540: (Warning -- Pointer member ' XXX::YYY ' neither freed nor zeroed by destructor -- Effective C++ #6)

       在析构函数中一定要把成员指针变量置为空指针,以免产生野指针,并且查看程序中是否有申请空间的操作,如果有一定要用delete或delete[]释放空间,如果没有则一定不要释放该指针指向的空间,把别人申请的空间释放掉,很可能引起错误。

5)error 545: (Warning -- Suspicious use of &)

       意思是“错误的使用了&”,定位到代码:

int array[100];
memset(&array, 0, sizeof(array));

原来我们多用了“&”, 改成:

memset(array, 0, sizeof(array));

就行了。其实array与&array都指向了同一个地址,但是要注意 array 和 &array 的类型是不同的。array 相当于 &array[0],而 &array 是一个指向 int[100] 的指针,类型是 int(*)[100]。array + 1指向数组的第二个元素,而&array + 1指向的地址已经超出了本数组的地址范围了。

6)error 616: (Warning -- control flows into case/default)
error 744: (Info -- switch statement has no default)
error 788:(Info -- enum constant 'Symbol' not used within defaulted switch)

       这3个警告都是与switch语句有关,都是在使用switch时最容易犯的错误,第一个是当一个case语句后面没有用break,程序会继续执行下一个case语句;第二个是没有写default语句;第三个是当使用enum类型作为switch值时,至少有一个enum变量没有出现在case语句中。

7)error 613: (Warning -- Possible use of null pointer ' 'XXX::YYY ' in left argument to operator '->')

       指针有可能为空,使用空指针会使程序崩溃的,在写代码时遇到使用指针时最好还是用if语句判断一下,或者assert断言一下。

8)error 1763: (Info -- Member function 'CXXX::YYY(void) const marked as const indirectly modifies class)

       成员函数被声明成const,但是成员变量的值有可能被间接改变,看一下函数的实现:

HTREEITEM CMGTreeCtrl::GetHitItem() const
{
    return m_TvhitLastClick.hItem;
}

函数被声明成const,表示这个函数不能改变成员变量的值,但当函数返回成员变量的指针或句柄时,成员变量的值就能被外部操作改变,这时要为返回值加上const,以便告诉调用者,不希望返回的指针或句柄所指向的内容的被改变。

9)error 773: (Info -- Expression-like macro 'LIST_DEVICE_MSG_ON_PAGE_CHANGE' not parenthesized)

       定位到代码:

#define LIST_DEVICE_MSG_ON_PAGE_CHANGE     WM_USER+1

定义宏时没有加括号,当程序预编译时,用WM_USER+1替换到代码中有可能产生非预期的结果,比如:

LIST_DEVICE_MSG_ON_PAGE_CHANGE - LIST_DEVICE_MSG_ON_PAGE_CHANGE

我们当然希望结果是0,但得到的结果却是2。

10)error 424: (Warning -- Inappropriate deallocation (delete) for 'new[]' data -- Effective C++ #5)

       使用new[]申请空间,但却使用delete释放空间,造成内存的泄漏,在使用时new与delete配对,new[]与delete[]配对。

11)error 1506: (Warning -- Call to virtual function ' 'XXX::YYY(void)' within a constructor or destructor)

       在构造函数或者析构函数中千万不要调用virtual函数,因为在base class构造函数中,virtual函数不会调用derived class中的虚函数,不会带来你所预想的结果。如果一定要使用virtual函数,请使用“类名::virtual函数”表示调用自身的函数,避免造成误解。

12)error 527:(Warning -- Unreachable code at token 'XX')

       不可到达的代码。可能是因为前面return掉了,后面的代码就永远不可能执行。通常是因为我们暂时屏蔽掉了某些功能但暂时没有删除其代码导致。可以用#if 0 来屏蔽之:

#if 0 //写出屏蔽原因
代码 
#endif

13)error 1925:(Note -- Symbol 'XXX::YYY' is a public data member) 
error 1536:(Warning -- Exposing low access member 'CXXX::m_XX') 

       在类设计时应该将所有成员变量为private,而不是public,因为:

(1)更精确的控制对成员变量的处理。如果成员变量是public的话,每个人都可以读写它,但如果时private的话,我们就可以通过是否提供setterXX、getterXX实现对成员变量的不准访问,只读,只写,读写多种方式。

(2)封装性,将成员变量隐藏在函数接口的背后,为以后修改接口提供方便。

14)error 578: (Warning -- Declaration of symbol ' XXX ' hides symbol ' XXX' (line 891))

       当前声明的XXX覆盖了891行声明的XXX,在一个变量的作用域下再次声明了一个同名的变量在语法上当然没有什么错误,但是这样会造成歧异,容易混淆,给别人阅读代码造成困难,不利于以后的维护。

15)error 661: (Warning -- Possible access of out-of-bounds pointer (22 beyond end of data) by operator '[')

        数组下标可能越界。

16)error 774: (Info -- Boolean within 'if' always evaluates to False)

        If判断语句的值始终为FALSE或者TRUE。

17)error 524: (Warning -- Loss of precision (arg. no. 3) (double to int))
error 732: (Info -- Loss of sign (arg. no. 1) (char to unsigned int))
error 713: (Info -- Loss of precision (arg. no. 1) (unsigned long to long))
error 573: (Warning -- Signed-unsigned mix with divide)
error 574: (Warning -- Signed-unsigned mix with relational)
error 747: (Info -- Significant prototype coercion unsigned long to double)
error 737: (Info -- Loss of sign in promotion from int to unsigned long)
error 734: (Info -- Loss of precision (arg. no. 2) (31 bits to 7 bits))
error 570: (Warning -- Loss of sign (initialization) (int to unsigned long))
error 569: (Warning -- Loss of information (assignment) (32 bits to 31 bits))
error 736: (Info -- Loss of precision (initialization) (55 bits to 32 bits))

       与精度丢失和符号错误相关的一些警告。

18)error 539: (Warning -- Did not expect positive indentation from line 529)

        代码格式没有对齐,这个时候,先选中没有对齐的代码,然后使用“ALT+F8”键,就可以对齐了。

19)error 715 (Symbol XXX not referenced)
error 752 (local declarator XXX not referenced)
error 550 (Symbol XXX  not accessed)
error 529 (Symbol XXX not subsequently referenced)
error 750    (Info -- local declarator 'XXX' macor not referenced)
error 751    (Info -- local typedef 'XXX' not referenced)

代码中声明了一些没有用过的东东。

20)error 685: (Warning -- Relational operator '>=' always evaluates to True)
error 775: (Info -- non-negative quantity cannot be less than zero)
error 568: (Warning -- non-negative quantity is never less than zero)

      if 语句中判断一个整数是否小于零, 而正数不可能小于零:

DWORD dwValue = XXX;
if( dwValue >= 0 )
if( dwValue < 0 )

21)其他错误

       以下的警告信息也是比较常见的信息,这里只做一些简单的列举:

error 818: (Info -- Pointer parameter 'Symbol' (Location) could be declared as pointing to const)//建议为指针参数加上const属性
error 1762: (Info -- Member function 'Symbol' could be made const)//建议为成员函数加上const属性
error 1746: (Info -- parameter could be made const reference)// 函数参数可以成为const引用
error 1764: (Info -- Reference parameter 'XX'  could be declared const ref) //建议为引用参数加上const属性

error 1732: (Info -- new in constructor for class 'CXXX' which has no assignment operator)//在类的构造函数中使用new申请了一块内存,但没有提供operator =。
error 1733: (Info -- new in constructor for class 'CXXX' which has no copy constructor )// 在类的构造函数中使用new申请了一块内存,但没有提供copy constructor。
注:在构造函数中使用new申请一块内存,可以推测在类中应该有一个成员变量指针指向该内存。当使用该类的一个对象去克隆另一个对象时,如果该类没有声明copy constructor或operator =,编译器将会自动生成一个默认的copy constructor或operator =,但默认的copy constructor与operator =都是“浅拷贝”,那么这2个对象的指针就指向了同一块内存地址,当一个对象析构时这块内存会被释放,另一个对象就会被破坏。

error 749: (Info -- local enumeration constant not ref)//定义了枚举常量却没有使用。
error 506: (Warning -- Constant value Boolean)//布尔值是个常量,导致if()或者while()每次都执行同样的路径。
error 669: (Warning -- Possible data overrun for function memcpy)//可能copy的数据过大
error 765: (Info -- external XXX could be made static)//只用在一个文件中的变量应当声明为static

error 429: (Warning -- Custodial pointer 'pXXX'has not been freed or returned)//内存可能没有释放 
error 1774: (Info -- Could use dynamic_cast to downcast polymorphic type 'CXXX')//建议使用dynamic_cast将一个父类转换成子类。
error 730: (Info -- Boolean argument to function)// 函数参数非 Boolean类型,但却传入了一个Boolean类型的数。
error 1551: (Warning--function may throw exception 'Name' in destructor 'Symbol' ) //析构函数抛异常

3、PC-Lint报告的语法错误

       以下列举的警告都是语法错误,基本上都是类型错误、重复定义、没有定义之类的东西,由编译器检查就OK了,不用用PC-lint来检查,一般情况下可以把这些信息屏蔽掉。

error 40: Undeclared identifier//标识符未定义
error 1055: Symbol 'XXX' undeclared, assumed to return int//函数没有定义,假定返回值为int
error 1015: Symbol 'XXX' not found in class //没有定义成员变量'XXX'
error 1013: Symbol 'XXX(OnInitialUpdate)' not a member of class 'YYY(CListView)' //'XXX’不是另一个成员函数
error 746: call to function 'XXX(IsKindOf())' not made in the presence of a prototype) //没有发现函数原型
error 38: Offset of symbol 'XXX' inconsistent (conflicts with other cpp)//    
error 113: (Error -- Inconsistent enum declaration)//枚举变量声明的顺序不一致(另一个模块有同名的枚举类型引起)
error 148: Error -- member 'Symbol' previously declared at Location//变量已经声明过了,重复声明
error 1039: (Error -- Symbol 'XX::YY()' is not a member of class 'XX')// YY()不是'XX'的成员函数
error 322: (Error -- Unable to open include file 'xx.h')//不能打开头文件
error 7: (Error -- Unable to open include file 'xx.h') //不能打开头文件
error 1074: (Error -- Expected a namespace identifier)//希望使用命名空间标识符
error 31: (Error -- Redefinition of symbol "XXX" compare with line)//重复定义 
error 14: Symbol 'XXX' previously defined//变量重复定义
error 1032: (Error -- Member 'XXX' cannot be called without object)//非static变量只能通过类的一个对象调用
error 58: (Error -- Bad type)指针不能与某个数比较 
error 63: (Error -- Expected an lvalue)//需要是一个左值
error 115: (Error -- struct/union not defined)//结构体后者枚举类型没有定义
error 770: (Info -- tag 'Symbol' defined identically at Location)//定义了相同的结构体或者联合体
error 64: type mismatch //类型不匹配
error 526: (Warning -- Symbol 'XXX'没有定义),变量没有定义
error 833: (Info -- Symbol 'XXX' is typed differently in another module)//变量在另一个模块中被定义成不同的类型
error 118: (Error -- Too few arguments )//传入的参数太少
error 55: (Error -- Bad type)//类型错误
error 1046: (Error -- Member 'CXXX::XX', referenced in a static function, requires an object)//非static变量只能不能被static函数调用

4、总结

       由于人工Code Review工作很耗精力,我们在程序进行编译测试前使用PC-lint进行代码检查,可以预先发现和规避很多错误,提高代码质量,节省测试时间,规范编码行为。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1038960.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

看文章-做笔记

看文章-做笔记 小蓝本

想要防止视频被盗?用它给视频加水印

随着社交网络的普及&#xff0c;越来越多的人喜欢在网上分享自己制作的视频&#xff0c;但是&#xff0c;共享的视频可能会被其他人传播和滥用。因此&#xff0c;保护自己制作的视频非常重要。 那怎样才能够防止别人盗用自己制作的视频呢&#xff1f;一种简单易行的保护方法是…

printContent 点击打印多页时第一页之前出现白页

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; printContent 点击打印多页时第一页之前出现白页 问题描述 提示&#xff1a;这里描述项目中遇到的问题&#xff1a; printContent 点击打印多页时第一页之前出现白页 原因分析&#xff1a; 提示&am…

【中阳期货】分析市场数据和制定交易策略代码

当谈到期货与市场分析时&#xff0c;编写代码来分析市场数据和制定交易策略是一种常见的做法。在这篇文章中&#xff0c;我将向您展示如何使用Python编写代码来获取市场数据、进行基本分析以及制定简单的交易策略。我们将使用一些常见的Python库&#xff0c;如Pandas、Matplotl…

前有CAP理论,后有BASE理论,分布式系统理论基石

&#x1f9d1;‍&#x1f4bb;作者名称&#xff1a;DaenCode &#x1f3a4;作者简介&#xff1a;CSDN实力新星&#xff0c;后端开发两年经验&#xff0c;曾担任甲方技术代表&#xff0c;业余独自创办智源恩创网络科技工作室。会点点Java相关技术栈、帆软报表、低代码平台快速开…

物联网如何改变智能家居技术?

物联网&#xff08;IoT&#xff09;已经在智能家居技术方面产生了深远的影响&#xff0c;其通过将各种设备、传感器和家居设备连接到互联网&#xff0c;实现了智能家居技术的创新和改进。 物联网(IoT)已经在智能家居技术方面产生了深远的影响&#xff0c;其通过将各种设备、传…

【手动实现nn.Linear 】

线性变换参数可视化图 class LinearLayer(nn.Module):def __init__(self, input_dim, output_dim):super(LinearLayer, self).__init__()self.weights nn.Parameter(torch.Tensor(output_dim, input_dim))self.bias nn.Parameter(torch.Tensor(output_dim))# 初始化权重和偏…

codesys自由编码器

1用于位置处理。 2它有个变量&#xff1a; SMC_FreeEncoder.diEncoderPosition 【DINT】 SMC_FreeEncoder_1.diEncoderPosition : GVL.电位器1; SMC_FreeEncoder.diEncoderPosition:hsi_cnt.diCurCountValue; //编码器位置 默认一圈是360.00 给它赋值&#x…

【AI画图】Stable Diffusion WebUI

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

机器学习西瓜书+南瓜书吃瓜教程学习笔记第三章(二)

南瓜书视频链接 以下是我的学习笔记 1、多元线性回归 首先跟着视频推了一遍&#xff0c;真的厉害&#xff0c;很清晰怎么来的 多元线性回归与一元线性回归同理利用最小二乘法求w和b。 这里我们讨论了如何使用线性模型进行回归学习&#xff0c;但若要做的是分类任务呢&#…

dhclient命令 – 动态获取或释放IP地址

参考链接&#xff1a;https://www.linuxcool.com/dhclient # dhclient命令 – 动态获取或释放IP地址 原文链接&#xff1a;https://www.linuxcool.com/dhclient

【计算机操作系统慕课版】第一章课后习题

课后习题目录&#xff1a; 一、简答题 1.在计算机系统上配置OS的目标是什么&#xff1f;作用表现在哪几个方面&#xff1f; 2.试说明OS与硬件、其他系统软件以及用户之间的关系。 3.试说明推动OS发展的主要动力是什么。 4.在OS中&#xff0c;何谓脱机I/O方式和联机I/O方式…

CVE-2023-42442:JumpServer堡垒机会话回放未授权访问漏洞复现

JumpServer堡垒机会话回放未授权访问漏洞&#xff08;CVE-2023-42442&#xff09; 0x01 前言 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人…

【系统架构】软件可靠性基础知识

导读&#xff1a;本文整理关于软件可靠性基础知识构建系统架构知识体系。完整和扎实的系统架构知识体系是作为架构设计的理论支撑&#xff0c;基于大量项目实践经验基础上&#xff0c;不断加深理论体系的理解&#xff0c;从而能够创造新解决系统相关问题。 目录 1、软件可靠性…

解决VSCODE 终端中显示中文乱码的问题

这里默认是UTF8 修改为GBK 选择通过编码保存 搜索GBK并选择即可 正常显示

【JVM】类加载子系统——自问自答

1、类加载的过程&#xff1a; java的类加载过程&#xff0c;是把字节码文件(.class file) 转换到JVM中运行时数据区内的过程。 类加载的过程由 类加载器子系统完成(Class Loader). 字节码文件可以像我们日常开发时在特定文件夹路径下的jar包里&#xff0c;也可以从网络中获取…

【RocketMQ】(七)事务实现原理

RocketMQ事务的使用场景 单体架构下的事务 在单体系统的开发过程中&#xff0c;假如某个场景下需要对数据库的多张表进行操作&#xff0c;为了保证数据的一致性&#xff0c;一般会使用事务&#xff0c;将所有的操作全部提交或者在出错的时候全部回滚。以创建订单为例&#xf…

6.5 图的遍历

前言&#xff1a; 主要内容&#xff1a; 这段文字描述的是图的遍历。图的遍历与树的遍历有些相似&#xff0c;都是从某个点开始&#xff0c;按照一定的规则遍历其他的点&#xff0c;但是图的遍历更加复杂&#xff0c;因为图中存在循环和回路&#xff0c;这意味着可能会多次访…

JavaWeb开发-09-MyBatis

官网&#xff1a;https://mybatis.org/mybatis-3/zh/index.html 一.Mybatis入门 1.快速入门 2.JDBC介绍 3.数据库连接池 官方地址&#xff1a;https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter 4.lombok 二.Mybatis基础增删改查 1.准备 2.删除 3.新增…

AT24C02芯片

AT24C02简介&#xff1a; AT24C01/02/04/08/16...是一个 1K/2K/4K/8K/16K 位串行 CMOS内部有9个字节&#xff1b; 该器件通过 I2C 总线接口进行 操作&#xff0c;它有一个专门的写保护功能&#xff1b; 基于51 他有这个芯片操作 时序&#xff1a; AT24C02软件编程&#xff1a; …