2021年C++项目中的十大Bug:乍一看都正确的代码,实则暗藏玄机!( 二 )


DefinePM_EXP2(A) ( 1<< (A)) 第7名:被除数与除数相混淆
V1064(https://pvs-studio.com/en/docs/warnings/v1064/)整数除法的操作数'gPEClockFrequencyInfo.bus_clock_rate_hz'小于'gPEClockFrequencyInfo.dec_clock_rate_hz' 。 结果始终为0 。
voidpe_identify_machine( __unused boot_args *args) {....// Start with default values.gPEClockFrequencyInfo.timebase_frequency_hz = 1000000000; gPEClockFrequencyInfo.bus_frequency_hz = 100000000; ....gPEClockFrequencyInfo.dec_clock_rate_hz =gPEClockFrequencyInfo.timebase_frequency_hz;gPEClockFrequencyInfo.bus_clock_rate_hz =gPEClockFrequencyInfo.bus_frequency_hz;....gPEClockFrequencyInfo.bus_to_dec_rate_den =gPEClockFrequencyInfo.bus_clock_rate_hz /gPEClockFrequencyInfo.dec_clock_rate_hz;} 所有字段都是整型:
externclock_frequency_info_tgPEClockFrequencyInfo; structclock_frequency_info_t{ unsignedlongbus_clock_rate_hz; unsignedlongdec_clock_rate_hz; unsignedlongbus_to_dec_rate_den; unsignedlonglongbus_frequency_hz; unsignedlongtimebase_frequency_hz; ....};
从名字来推测 , 除数和被除数写反了 。
第6名:选择类型时的错误
V610(https://pvs-studio.com/en/docs/warnings/v610/)未定义的行为 。 请检查移位操作符'>>=' 。 右边的操作数 ('bitpos % 64' = [0..63])大于或等于左边的操作数的位长 。
// bitsperlong.h# ifdefCONFIG_64BIT # defineBITS_PER_LONG 64 # else# defineBITS_PER_LONG 32 # endif/* CONFIG_64BIT */// bits.h/** Create a contiguous bitmask starting at bit position @l and ending at* position @h. For example* GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000.*/# define__GENMASK(h, l) ....
// master.h# defineI2C_MAX_ADDR GENMASK(6, 0)
// master.cstaticenumi3c_addr_slot_status i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr){intstatus, bitpos = addr * 2; // <=
if(addr > I2C_MAX_ADDR) returnI3C_ADDR_SLOT_RSVD;
status = bus->addrslots[bitpos / BITS_PER_LONG];status >>= bitpos % BITS_PER_LONG; // <=
returnstatus & I3C_ADDR_SLOT_STATUS_MASK; }
注意BITS_PER_LONG宏可以是64位的 。
这段代码包含以下未定义的行为:
● 在检查后 , addr变量的取值范围为[0..127]
● 如果参数 addr >= 16 , 那么status变量的右移位数将超过int类型包含的比特数
也许作者想要减少代码行数 , 所以bitpos变量的定义紧跟status 。 但是 , 作者并没有考虑到int与long不同 , 它在64位平台上只有32位 。
要改正这个错误 , 应该将status变量定义成long 。
第5名:模块间的分析和丢失的memset
今年 , 我们添加了一个重要功能:对C++项目进行模块间分析 。 这个功能找到了codelite项目中的以下警告 。
V597(https://pvs-studio.com/en/docs/warnings/v597/)编译器可能会删掉'memset'函数调用 , 该函数调用会给'current'赋值 。 擦除私有数据应该使用memset_s 。 )
// args.cexternvoideFree( void* constptr) ; externvoidargDelete(Arguments* constcurrent) {Assert (current != NULL); if(current->type == ARG_STRING && current->item != NULL) eFree (current->item);memset(current, 0, sizeof(Arguments)); // <=eFree (current); // <=}// routines.cexternvoideFree( void* constptr) {Assert (ptr != NULL); free(ptr); }LTO(连接时间分析)使用了memset调用 。 编译器通过 as-if 规则发现 , eFree并没有计算出任何有用的指针相关的数据 。 eFree只是调用了free函数来释放内存 。

特别声明:本站内容均来自网友提供或互联网,仅供参考,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。