我知道一些CPU架构不支持未对齐的地址访问(例如,ARM4之前的ARM架构没有访问内存中半字对象的指令)。针对该体系结构的一些编译器(例如,某个版本的GCC)在发现未对齐的地址时会使用一系列内存访问,因此未对齐的访问对开发人员几乎是透明的。(请参阅The Definitive Guide to GCC, By William von Hagen)
但我想知道编译器如何知道地址是否对齐?毕竟,编译器看到的是虚拟地址(有效地址,EA),如果它能看到任何东西的话。当程序运行时,EA可以被操作系统映射到任何物理地址。即使虚拟地址是对齐的,产生的物理地址也可能是未对齐的,不是吗?物理地址的对齐才是真正重要的,并在CPU地址线上传输。
因为编译器根本不知道物理地址,它如何智能地知道变量的地址是否对齐呢?
发布于 2012-12-19 21:53:37
虚拟地址并不只是映射到任何物理地址。虚拟内存是以对齐的方式映射到物理页面的页面。(通常对齐到4096)。
请参阅:Virtual memory and alignment - how do they factor together?
发布于 2012-12-19 22:57:01
对齐对于目标代码来说是一个非常有用的属性,部分原因是一些机器坚持“对齐访问”,但在现代计算机中,因为缓存线对性能有巨大的影响,因此代码/循环/数据/锁的缓存对齐是本地友好编译器的要求。
实际上,世界上所有的加载器都支持在中等大小的2次方对齐的边界上加载代码。(汇编器和链接器也通过各种对齐指令支持这一点)。通常,链接器和加载器只是将第一个加载的值与众所周知的边界大小对齐;具有虚拟内存的OSes通常会根据VM页面大小提供一个方便的边界(与其他答案相关)。
因此,编译器基本上可以知道其发出的代码/数据的对齐方式。通过跟踪它发出的代码量,它可以知道任何发出的值的对齐方式。如果它需要对齐,它可以发出一个链接器指令,或者对于中等大小,只需填充,直到发出的代码量适当对齐。
因此,您可以非常肯定的是,大多数编译器不会以跨越缓存线(或其他架构强加的)边界的方式放置代码或数据构造,除非被指示这样做,否则会对性能产生重大影响。
https://stackoverflow.com/questions/13953834
复制相似问题