最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【经验教训】使用强制类型转换时候,一定要慎重

经验和教训 crifan 3243浏览 0评论

【过程记录】

之前别人实现的驱动中的一个函数中,实际实现的功能是读或写一个的寄存器。对应操作数都是8位的u8,但是却在函数参数中,设计成int型的u32 ,导致,函数读/写寄存器之后,将得到的寄存器的值返回,给传入的buffer,此时已经设计成u32*了,所以

int afe_read_reg(int addr, u32* pdata)
{

u8 msgbuf[1];

。。。。
*pdata = msgbuf[0];

}

所以,此时的值,虽然msgbuf[0];是u8,但是赋值左边是u32 。所以,即使传入的地址是u8 *而被强制转换成u32*了,此时,真正传入的地址之后的3个字节,也就会被清0了。所以,就会出现问题。

此处之所以会出现这样的问题就是,

read reg虽然被设计成打算支持以后u16和u32和当前的u8,但是,这样的设计,却没有和此函数的调用者同步好,另外某个文件中,大量调用afe read reg这个函数,但是,全部都是用u8的变量的地址传入此函数的,所以,此隐患,早晚会错误。

而我此处就是在调试一个字符型设备system monitor的seq file的start, next ,show等函数实现时候,出现了问题。

对于很简单的3个变量:

unsigned int bat_volt;
int chg_connected;
int usb_connected;

通过函数调用,其最终也会用到read reg,然后将返回值赋值给这些变量,接下来的show函数中去打印。逻辑本身就很简单和清晰,但是实际的情况是,bat_volt和chg_connected,总有一个值是不正常的,开始以为你对齐alligned或者填充padding方面的问题,但是最后发现不是,调试出来的现象是,将两个函数赋值的地方,换一下,就好了。或者是添加一个中间变量存储一下从通过read reg函数的返回值,再赋值给这些值,有时候就可以了。

最后是确认,就是read reg的函数有问题,把int afe_read_reg(int addr, u32* pdata)变成int afe_read_reg(int addr, u8* pdata),然后其他调用read reg的程序,就都表现正常了。

【经验教训】

1.函数实现和函数调用的时候,一定要注意传入给函数的变量,是否和函数声明中的类型是否一致,

否则,很可能会出现,参数传入的变量的宽度太小,比如是unsiged char,只是个u8,而实际函数里面使用到的是u32 ,此时对u32操作的话,就会影响到传入的u8的后面3个字节。

2.设计函数和使用函数,一定要明确自己的职责和意图,不可含混,即使打算设计成具有一定扩展性的函数,那么也要加上一定的注释。

3.很多事情的罪魁祸首,都是做事情时候,在当时,觉得只是暂时这么做,等其他地方确定了之后,再回来确定此处的内容,但是实际往往是留下了自己都没注意到的bug或者不妥的地方。所以,做事情,第一次就要努力做对,不要给自己机会再来改。

转载请注明:在路上 » 【经验教训】使用强制类型转换时候,一定要慎重

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
79 queries in 0.154 seconds, using 21.96MB memory