这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 综合技术 » 基础知识 » 【我踩过的那些坑】未引用头文件导致uint64格式数据获取异常

共2条 1/1 1 跳转至

【我踩过的那些坑】未引用头文件导致uint64格式数据获取异常

高工
2025-10-22 22:46:35     打赏

背景

        客户拿我们做的机器对接外部供应商的算法,在对接算法过程中,外部供应商反馈我们的机器读到的IMU数据中的时间戳有时会变成负数。

分析过程

        从负责此IMU模块驱动模块的同事处了解到,这个时间并不是IMU的时钟,而是使用的平台自带的时钟,暂不确定是哪出了问题。随机让同事加调试信息,安排煲机,经过漫长的煲机,发现确实会出现负数的情况。

        此时让同事用%llx的方式继续抓,从抓到的log中看,发现在数据增加到0x7FFFFFFF后,只要数据再增加,后面的数据就会变成负数,但是呢,底层上报额数据是uint64_t格式的,有点无厘头。

        由于同事加的log不全,并没有体现是哪一层出的问题,遂让同事加全log(主要是加各层的接收和向下一层上报处的log)煲机。煲机后发现在获取时间戳时就已经出异常了。

       此时同事针对性的查看代码,发现代码并无异常,代码的伪代码为:

a.c


uint64_t get_time(void)
{
    return xxxx; // 此处为芯片寄存器值
}

b.c

uint64_t get_info(struct sensor_data *dat)
{
    dat->xxxx = xxxx;
    
    ....
    dat->time = get_time()); // 此处的time也为uint64_t的结构
}

        从代码上来看,这个逻辑没毛病,从一个返回值为uint64_t的函数中读到数据直接赋值给uing64_t的变量,没有任何问题。

        但是考虑到此时发生了翻转,遂怀疑是不是寄存器本身给的信息错误,此时让同事将寄存器值改为变量值,每次读取时,变量都增加,查看是否异常,此时发现异常仍然存在,可以排除芯片本身设计问题。

        由于数据发生突变,此时怀疑是不是参数值传递时出现异常,因此让同事确认包含get_time函数的头文件是否被b,c申明,此时一查,还真发现了问题,头文件并未被引用,遂让同事加上头文件后再次测试。经过测试,问题消失。

后续处理

        1. 让同事排查所有用到此函数的c文件是否都有引用该头文件,确认完毕后出软件提交测试。测试通过后将修改项合并至代码主干。

        2. 顺便让同事修改好上层接口,将上层读取数据结构体中的时间信息的格式与底层统一,确保不会出现数据交互时的信息突变。

背后原理

        在头文件未包裹的情况下,编译器会根据设定的规则去确认是否按报错处理,刚好我们拿到的供应商代码使用的是相对宽松的规则,此时编译时仅仅会报函数不存在,默认使用 int get_time(void)的虚拟接口编译成中间文件,而在链接时,由于函数uint64_t get_time(void)在另一个中间文件中存在,因此链接是也没报错。

        恰恰就是这种宽松的逻辑带来了问题,虽然函数返回值是uint64_t格式的,但当b.c那边调用时,会将uint64_t格式的数据转成int格式给到dat->time,此时由于uint64_t 到int时,不是强制类型转换,而是仅仅类似于共享内存的方式(两边各自按照各自的格式去读写,读操作并不改变存储的值),也就造成了0x8000000在int格式时对应的也是0x80000000。

        之后又执行了一遍赋值操作,此时0x80000000由于高位为1,到uint64_t时,高位都会被补1。但此时还是不会有异常,因为格式是uint64_t。偏偏我们拿到的代码又有另一个坑,内核给的time是uint64_t,framework读数据时用的是int64_t,而数据交互过程又是采用共享内存的方式实现的,这就导致了上层拿到的数据因为最高位为1直接变成了负数了。





关键词: 我踩过的那些坑     头文件未引用导致的神奇问题    

助工
2025-10-23 17:18:41     打赏
2楼

操作64位数据格式比较少,很容易就忽略了。


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]