嵌入式开发——结构体指针作为参数传递变量的值不正确
Posted 代二毛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了嵌入式开发——结构体指针作为参数传递变量的值不正确相关的知识,希望对你有一定的参考价值。
问题描述
由于海思芯片紧缺,公司决定启用一款新的音视频处理芯片,我负责要将原有的算法库移植到新平台。在移植的过程中,发现调用某个图像转换函数时,得不到正确的结果,而且这个函数还是其他的库里实现的,我只是调用。于是我去查看了这个函数的实现,传参主要是通过一个结构体。我在调用这个函数前,将该结构体的成员变量的值都打印出来,发现没有问题,然后在被调用的函数里,打印接收到的变量的值,发现对不上。这就很奇怪了,明明我在调用函数前赋值都是正确的,为什么传进去就不对了,百思不得其解。简单来说,就是我在A库调用B库实现的函数时,发现通过结构体传参,传过去的变量的值不正确。
解决步骤:
1.传参是传的结构体指针,我在调用函数前打印了这个结构体指针,在被调用函数里也打印了这个结构体指针,发现指针是一样的,表明传参是没有问题的。这里存在两种出错的可能,一种是两者数据解析方式不同,毕竟传的是同一内存地址,数据都一样;还有一种可能是该内存地址处的数据被意向不到的地方给修改了,导致两次去读取该内存的数据不一样。
2.接着进一步添加打印,我把结构体里的每个成员变量的地址都打印出来,发现在调用前打印和在被调用函数里打印是不一样的,这就能解释为什么传参的值不正确了,因为两次读取的都不是同一内存地址处的数据。这让我想起来结构体的对齐,毕竟面试时候考结构体最喜欢考对齐,于是我用sizeof()函数在两个库都打印了该结构体占用的字节数,果然两个库里同一结构体占用的字节数不一样,由此推断是两个库的对齐字节数不同导致的。
3.两个库都是运行在同一芯片,默认的对齐字节数就是CPU的位宽,32位机器就是4byte,64位芯片就是8byte。肯定有地方强行修改了对齐字节数,于是我用比对软件对比两个库里同一头文件的差异,发现其中一个库用了#pragma pack(4)将对齐字节数强行修改成4字节,这才导致两个库里结构体不一样。不熟悉的可以参考博客《嵌入式开发——#pragma pack()常见用法介绍》。
4.因为海思芯片是32位的,默认就是4byte对齐,所以加不加#pragma pack(4)都是4字节对齐,代码在海思芯片上运行就没有问题。现在移植到的新芯片是64位的,默认是8字节对齐,这样就导致A库是8字节对齐,B库是4字节对齐,导致结构体大小不同,成员变量的地址相对于结构体首地址的偏移量也不同,肯定不能解析出正确的数据。
总结
我遇到的这种情况,最根本的原因就是两个库的交互头文件不一致导致的,正常情况两个库里的同一头文件应该是相同的。这是个历史遗留问题,以前被掩盖了,现在移植新平台才显露出来。同时也提醒自己,修改库之间交互的头文件要慎重。
以上是关于嵌入式开发——结构体指针作为参数传递变量的值不正确的主要内容,如果未能解决你的问题,请参考以下文章
C 语言结构体 ( 结构体作为函数参数 | 结构体指针作为函数参数 )