BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / embedded-system / #7291同步于 2010/1/9
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Embedded_System机器人发帖

交叉编译器导致sizeof结果不一致

ArmStrong
2010/1/9镜像同步11 回复
刚刚解决了一个问题 一个程序莫名其妙地就运行不了了 仔细检查之后发现原来是一个宏里面包含sizeof(某数据结构) 在4.2版本的arm-linux-gcc 下这个sizeof的结果是16 在3.4.3版本下结果是24 略有无语。。。开始怎么也没想到是这个问题,以为是代码版本控制或者硬件出了问题
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
yihang机器人#1 · 2010/1/9
【 在 ArmStrong 的大作中提到: 】 : 刚刚解决了一个问题 : 一个程序莫名其妙地就运行不了了 : 仔细检查之后发现原来是一个宏里面包含sizeof(某数据结构) : ................... vc6 和 gcc 这个sizeof 处理对结构体来说就很多不一样 在笔试时出这种题有时候让人无所适从。 (按常规处理发现没有答案就很郁闷)
hobby机器人#2 · 2010/1/9
数据结构有做attribute packed吗? 如果设置了但还是有变化的话,那就不可理解了 【 在 ArmStrong (奶瓶) 的大作中提到: 】 : 刚刚解决了一个问题 : 一个程序莫名其妙地就运行不了了 : 仔细检查之后发现原来是一个宏里面包含sizeof(某数据结构) : ...................
ArmStrong机器人#3 · 2010/1/9
没用过这dd,我试一下,不过内核里基本上很少用这个啊。 【 在 hobby (hobby) 的大作中提到: 】 : 数据结构有做attribute packed吗? : 如果设置了但还是有变化的话,那就不可理解了
hobby机器人#4 · 2010/1/10
如果是协议报文啥的,有的对字节顺序有严格要求,不能允许出现struct为了对齐进行的填充,这样的应该就需要packed, 至于其他的比如fd,net_device什么的,应该没要求了吧 不过话说回来,搜了一下,内核里用的的确不多,刚才在2.6.13的kernel代码里才搜出来500多个,不知道为啥(而且像TCP头这样的竟然也没加) 【 在 ArmStrong (奶瓶) 的大作中提到: 】 : 没用过这dd,我试一下,不过内核里基本上很少用这个啊。
ssailing机器人#5 · 2010/1/10
【 在 hobby 的大作中提到: 】 : 如果是协议报文啥的,有的对字节顺序有严格要求,不能允许出现struct为了对齐进行的填充,这样的应该就需要packed, : 至于其他的比如fd,net_device什么的,应该没要求了吧 : 不过话说回来,搜了一下,内核里用的的确不多,刚才在2.6.13的kernel代码里才搜出来500多个,不知道为啥(而且像TCP头这样的竟然也没加) : ................... 首先明确一点,基于不同CPU甚至是相同的CPU但不同的编译器版本 对结构体的对齐都可能不一样 结构体为什么需要对齐? 一是因为跨CPU通信 需要保证双方对数据的解析一致 这就要求有相同的对齐规则 二是因为 非对齐的数据 需要多个存储器访问周期才能取得所需要的数据 造成效率低下 当然这个低下 你从C语言级别是看不出来的 汇编指令级也看不出来 只能从存储器的总线时序上看 所以编译器一般会自动对齐 以空间换时间 三是因为 有些CPU不支持非对齐访问 为什么不支持 因为效率低 干脆直接当异常处理得了 据我所知X86在硬件级别支持非对齐访问 也就是说不对齐的问题 软件无法感知 但MIPS 龙芯 Sparc PPC ARM等就不支持非对齐访问 这时候会抛出一个异常 有些操作系统如Linux会自动对异常进行纠正 保证得到正确的值 对程序员来说 你不会觉得有任何问题 但是对于OS来说 那可是费了九牛二虎之力啊 如何改变结构体的对齐规则? 可以人为的改变对齐规则 但是不同的方法 控制的粒度是不一样的 makefile可以控制整个工程的对齐规则 pragma pack(n)和pragma pack(n)配合可以控制此区间的对齐规则 __attribute((packed (n))可以控制特定的结构体的对齐规则 可见影响一个结构体大小的因素太多了 是不是结构体对齐了就能保证程序没有问题呢 显然不是 是否对齐只是改变了数据的存储方式 并不能改变CPU访问数据的方式 对于不支持非对齐访问的CPU 在半字地址访问字仍然会造成异常 虽说OS能够处理这个异常 但是代价太大了 这样倒不如直接告诉编译器 默认以非对齐的方式来访问数据 这正式__attribute((packed (n))的功能 也是区别于其他改变对齐规则的机制 这个时候会编译成多条指令来访问__attribute((packed (n))修饰的数据 相对于OS异常处理来说代价小了 但相对于对齐访问来说 还是有代价 想想如果通篇都是这样的数据 一个字都得分成4个字节来访问 那效率是指数下降的 如何保证自动对齐?如何避免访存失败?如何提高访存效率? 那么我们怎么样才能保证我们定义的结构体不随着平台及编译器的版本而变化呢 合理调整成员的顺序及人为的进行填充 保证已经对齐了 这样不论什么编译器 结构体的大小都是固定的 因为是对齐的数据 无论CPU是否支持非对齐访问 都不会产生异常 因为是对齐访问 所以不会损失效率 唯一的代价就是浪费了一定人为填充的空间 但这一点空间效率的损失带来的效益却是无穷的 不光程序运行的效率提高了 程序跨平台的可移植性也强了 在任意的CPU上都有一致的表现 Windows程序员永远不需要为内存对齐操心 但他们太安乐了 也享受不到异常带来的刺激 这也正是嵌入式程序员的幸福所在 因为有问题 所以我们才会懂的更多 痛 但我们快乐着
ssailing机器人#6 · 2010/1/10
【 在 hobby 的大作中提到: 】 : 如果是协议报文啥的,有的对字节顺序有严格要求,不能允许出现struct为了对齐进行的填充,这样的应该就需要packed, : 至于其他的比如fd,net_device什么的,应该没要求了吧 : 不过话说回来,搜了一下,内核里用的的确不多,刚才在2.6.13的kernel代码里才搜出来500多个,不知道为啥(而且像TCP头这样的竟然也没加) : ................... 对 跨处理器通信的协议报文 更是需要对齐 packed有此功能 为什么TCP头没有pack修饰 那是因为其本身已经是字对齐的 何需多此一举呢 仔细研究下 你会发现 协议头及协议内容在设计的时候 都考虑过对齐的问题了 即使相应位没有意义 也会自动填充 作为保留位 一为将来扩展之用 二就是为了对齐 只有我们自己设计的协议 不规范的时候 才会出现对齐的问题 曾经实习的时候就遇到过类似的问题 原有的程序不规范 在跨平台移植的时候就出问题了 当时真是头大啊。。。 内核数据结构在设计的时候 多数都考虑了对齐的问题 所有用packed之类的关键字对齐的很少
ssailing机器人#7 · 2010/1/10
【 在 ArmStrong 的大作中提到: 】 : 刚刚解决了一个问题 : 一个程序莫名其妙地就运行不了了 : 仔细检查之后发现原来是一个宏里面包含sizeof(某数据结构) : ................... 版主大人 能把这个结构体贴上来 让大家学习学习么
hobby机器人#8 · 2010/1/10
唉,每次看你讲的这么专业,我都觉得自己很山寨…… 掩面飘走…… 【 在 ssailing (sailing) 的大作中提到: 】 : 首先明确一点,基于不同CPU甚至是相同的CPU但不同的编译器版本 : 对结构体的对齐都可能不一样 : 结构体为什么需要对齐? : ...................
ArmStrong机器人#9 · 2010/1/11
多谢,学习了! 结构体里主要有影响的东西就是enum,这个东西对齐与否是影响大小的 【 在 ssailing (sailing) 的大作中提到: 】 : 首先明确一点,基于不同CPU甚至是相同的CPU但不同的编译器版本 : 对结构体的对齐都可能不一样 : 结构体为什么需要对齐? : ...................