您的位置:首页 > 其它

结构体成员非对齐访问所带来的思考

2010-01-12 00:01 288 查看
结构体成员非对齐访问所带来的思考

Sailor_forever sailing_9806#163.com

(本原创文章发表于Sailor_forever 的个人blog,未经本人许可,不得用于商业用途。任何个人、媒体、其他网站不得私自抄袭;网络媒体转载请注明出处,增加原文链接,否则属于侵权行为。如有任何问题,请留言或者发邮件给sailing_9806#163.com)

http://blog.csdn.net/sailor_8318/archive/2010/01/12/5178990.aspx

【摘要】本文介绍了内存访问时为什么需要对齐及不对齐时带来的影响。接着介绍了如何改变对齐规则来保证CPU能够访问非对齐内存。最后介绍了结构体设计时需要注意的问题,如何调整成员顺序或者填充特定单元来避免平台差异所带来的潜在异常。

【关键字】X86 MIPS PowerPC alignment exception 非对齐访问 存储器周期

1 问题的引子

在论坛上看到的一个帖子,如下:

//////////////////////////////

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

刚刚解决了一个问题

一个程序莫名其妙地就运行不了了

仔细检查之后发现原来是一个宏里面包含sizeof(某数据结构)

在4.2版本的arm-linux-gcc 下这个sizeof的结果是16

在3.4.3版本下结果是24

略有无语。。。开始怎么也没想到是这个问题,以为是代码版本控制或者硬件出了问题

/////////////////////////////////

首先明确一点,基于不同CPU甚至是相同的CPU但不同的编译器版本

对结构体的对齐都可能不一样,这就将导致结构体大小的差异

2 结构体为什么需要对齐?

一是因为跨CPU通信 需要保证双方对数据的解析一致 这就要求有相同的对齐规则

二是因为 非对齐的数据 需要多个存储器访问周期才能取得所需要的数据 造成效率低下 当然这个低下 你从C语言级别是看不出来的 汇编指令级也看不出来 只能从存储器的总线时序上看

所以编译器一般会自动对齐 以空间换时间

三是因为 有些CPU不支持非对齐访问 为什么不支持 因为效率低 干脆直接当异常处理得了

据我所知X86在硬件级别支持非对齐访问 也就是说不对齐的问题 软件无法感知

但MIPS 龙芯 Sparc PPC ARM等就不支持非对齐访问 这时候会抛出一个异常

有些操作系统如Linux会自动对异常进行纠正 保证得到正确的值

对程序员来说 你不会觉得有任何问题 但是对于OS来说 那可是费了九牛二虎之力啊

3 如何改变结构体的对齐规则?

可以人为的改变对齐规则 但是不同的方法 控制的粒度是不一样的

makefile可以控制整个工程的对齐规则

pragma pack(n)和pragma pack(n)配合可以控制此区间的对齐规则

__attribute((packed (n))可以控制特定的结构体的对齐规则

可见影响一个结构体大小的因素太多了

是不是结构体对齐了就能保证程序没有问题呢 显然不是

是否对齐只是改变了数据的存储方式 并不能改变CPU访问数据的方式

对于不支持非对齐访问的CPU 在半字地址访问字仍然会造成异常

虽说OS能够处理这个异常 但是代价太大了

这样倒不如直接告诉编译器 默认以非对齐的方式来访问数据

这正式__attribute((packed (n))的功能 也是区别于其他改变对齐规则的机制

这个时候会编译成多条指令来访问__attribute((packed (n))修饰的数据

相对于OS异常处理来说代价小了 但相对于对齐访问来说 还是有代价

想想如果通篇都是这样的数据 一个字都得分成4个字节来访问 那效率是指数下降的

4 如何保证自动对齐?如何避免访存失败?如何提高访存效率?

那么我们怎么样才能保证我们定义的结构体不随着平台及编译器的版本而变化呢

合理调整成员的顺序及人为的进行填充 保证已经对齐了

这样不论什么编译器 结构体的大小都是固定的

因为是对齐的数据 无论CPU是否支持非对齐访问 都不会产生异常

因为是对齐访问 所以不会损失效率

唯一的代价就是浪费了一定人为填充的空间

但这一点空间效率的损失带来的效益却是无穷的

不光程序运行的效率提高了 程序跨平台的可移植性也强了 在任意的CPU上都有一致的表现

其实除了结构体会带来非对齐访问的问题,指针的强制转换也是一个潜在的不对齐的问题。因此应该避免强制进行指针转换,而是让编译器以warning的形式告诉我们,这样可以确认这个强制转换是否有问题。

Windows程序员永远不需要为内存对齐问题操心费神

但他们太安乐了 可惜的是也享受不到异常带来的刺激

这也正是嵌入式程序员的幸福所在 因为有问题 所以我们才会懂的更多

痛 但我们快乐着

一个很有趣的帖子,问题虽小,但却折射了很多问题,直接看到凌晨三点多,还是很带劲
http://topic.csdn.net/t/20030707/17/2000453.html#
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: