版权声明:转载自 http://hi.baidu.com/kobetec/blog/item/dd18ea344d5613b3d1a2d351.html 关于内存对齐的话题,始终是敏感的。稍有不慎,必将闯下大祸!最近项目稍显轻闲,自己给自己安排一天反思和总结一下,突然想到以前写过的一篇'也谈内存对齐',那篇文章谈的是内存对齐的基本知识以及一些实验的数据,想必很多人看完后,会收获一些东西,但是对内存对齐的应用还是处于懵懂状态,其实大部分时间我们是不会显式的用到'内存对齐的',但是有些时候我们需要这样做。这里做了一个小例子,希望能给大家以启发。 例子是这样的:我们有一种二进制文件,其中存储了多条经过特定对齐的某种记录格式的数据,我们的任务就是解析出来这些数据,但是我们不知道也没有这种数据的记录格式结构的定义,但我们不是一无所有,我们有一个表,这个表描述了这个记录格式中有哪些域以及这些域的类型信息,我们还知道的是源数据的对齐系数。 叙述完问题后,我们来给出一些具体的东西: 二进制文件生成程序: int main() { fp = fopen("foo.dat", "wb+"); fwrite(&foo1, sizeof(foo1), 1, fp); fclose(fp); return 0; 生成的待解析文件:foo.dat,其中有两条记录。 好了,我们的任务已经很明确了,就是正确解析出这两条记录。如果解析程序知道有下面这样的结构体定义: #define X_CHAR 1 typedef struct x_fld_info_t { x_fld_info_t cpi_type_info_tab[3] = { /* cpi - composite */ 想一想,我们能从文件foo.dat中读出来什么?仅仅是一块数据,每次读多大一块?如何在这块数据中找到相应的域呢?没错,我们需要通过 cpi_type_info_tab这个表信息得出每条foo_t记录的大小,还要得到foo_t中每个域在这块数据中的偏移量,然后根据偏移量和域自身大小准确获取其内容。 好了终于要用到内存对齐的知识了,其实想想也知道foo.dat的文件生成程序和我们的解析程序可能不在一台机器上,而且完全可能在体系结构不同的机器上,这样不同体系结构的机器他们的默认对齐系数、字节序都可能不同(这里我们暂不考虑字节序的问题),我们在文件生成程序那边强制指定对齐系数有利于解析程序这边的解析。我们要做的就是根据已知的对齐系数和cpi_type_info_tab表中的信息计算出来该结构体在特定对齐系数下的总大小以及其各个域的偏移量。下面的宏X_ROUND_UP和函数align_cpi_type配合完成了这一工作: int x_atom_type_size[4] = { static int lg2(int k) { /* 这里假设k一定为2的次方^_^ */ while ((k /= 2) != 0) { #define X_ROUND_UP(x, k, rv) do { / static void align_cpi_type(x_fld_info_t *tab, int fld_cnt, int force_align_mod, int *size) { /* if (atom_sz < modules) { X_ROUND_UP(cur, lg2(ali_mod), rv); /* X_ROUND_UP(cur, lg2(ali_mod), rv); 如果对内存对齐还有疑惑的,可以去看看我的那篇'也谈内存对齐',再回到这来看align_cpi_type的实现,这里的X_ROUND_UP的算法借自于'Hacker's Delight' 一书,很好的一本讨论'Computer Arithmetic'的书,里面的很多Knowledge & Tip很有价值。通过align_cpi_type函数我们既得到了结构的大小也得到了结构中各个域的偏移量。根据这些信息我们就可以输出文件 foo.dat中的数据了。 static void output_cpi_mem(x_fld_info_t *tab, int fld_cnt, char *buf) for (i = 0; i < fld_cnt; i++) { int main() { int size = 0; align_cpi_type(cpi_type_info_tab, sizeof(cpi_type_info_tab)/sizeof(cpi_type_info_tab[0]), modules, &size); /*
for (i = 0; i < 2; i++) { /* 这里偷了个懒儿,直接用2这个记录的个数了 */ /* fclose(fp); return 0; 执行输出: 看到这有些人可能还是很糊涂,到底为什么要这么做呢?提示一下:现在我们要解析一存储未知类型数据的文件的记录时,我们只需要这个纪录的一些描述信息即可了,而无需知道那个foo_t的具体定义了。能不能理解就看你自己了。 |
内存对齐与文件分析
最新推荐文章于 2022-10-25 11:06:20 发布