项目中有时会遇到字节对齐的问题,英文为“Alignment trap”,如果直译,意思为“对齐陷阱”,不过这个说法不太好理解,还是直接用英文来表达。

ARM平台下一般是4字节对齐,可以参考文后的给出的文章链接。此处不细说。后面提及“字节对齐”

下面的例子使用了几种重现Alignment trap的方法,例子1是将char*指针直接转换成int*指针,经测试,未发现有字节对齐的问题。例子2和例子3相似,主要是结构体中的字段没有进行对齐(或者访问的地址没有4字节对齐)。例子4是直接访问了没有字节对齐的指针。后3个例子在测试时均出现了错误。

/**
 *
 Linux下对Alignment trap的处理有下面几种方式:
 0 (ignored)
 1 (warn)
 2 (fixup)
 3 (fixup+warn)
 4 (signal)
 5 (signal+warn)

使用方法:
 # echo 3 > /proc/cpu/alignment
 */

#include <stdio.h>
#include <stdlib.h>

/// case 1
void fool(unsigned char* buf, int len)
{
    unsigned int* p = (unsigned int*)buf;
    int i;

for (i = 0; i < len; i++)
    {
        *p++ = i+1;
        printf("%d ", *p);
    }
}

void foolish()
{
    unsigned char poor[100];

fool(poor, sizeof(poor)/sizeof(int));
    
}

// case 1 end
////////////////////////////////////////////////////////////////

/// case 2

struct rte_unpacked_struct_t
{
    char c1;
    int i;
    char c2;
    short s1;
    char c3;
};

struct rte_packed_struct_t
{
    char c1;
    int i;
    char c2;
    short s1;
    char c3;
}__attribute__((__packed__));

struct rte_unpacked_struct_t unpacked;
struct rte_packed_struct_t packed;

void print_addr()
{
    printf("sizeof(unpacked) = %d sizeof(packed) = %d\n", sizeof(unpacked), sizeof(packed));
    printf("Addr of unpacked: %p\n", &unpacked);
    printf("Addr of unpacked.c1: %p\n", &unpacked.c1);
    printf("Addr of unpacked.i: %p\n", &unpacked.i);
    printf("Addr of unpacked.c2: %p\n", &unpacked.c2);
    printf("Addr of unpacked.s1: %p\n", &unpacked.s1);
    printf("Addr of unpacked.c3: %p\n", &unpacked.c3);

printf("Addr of packed: %p\n", &packed);
    printf("Addr of packed.c1: %p\n", &packed.c1);
    printf("Addr of packed.i: %p\n", &packed.i);
    printf("Addr of packed.c2: %p\n", &packed.c2);
    printf("Addr of packed.s1: %p\n", &packed.s1);
    printf("Addr of packed.c3: %p\n", &packed.c3);

}

short* rte_get_s1(void)
{
    return &unpacked.s1;
}

void case2()
{
    print_addr();

int* val = (int *)rte_get_s1();
    printf("val = %d\n", *val);    
}
/// case 2 end
////////////////////////////////////////////////////////////////

/// case 3
struct foo_t
{
    short a;
    short b;
    short c;
    short d;
};

struct foo_t foo;

short* get_foo_c(void)
{
    return &foo.c;
}

void case3()
{
    printf("sizeof(foo) = %d\n", sizeof(foo));
    // 注意!!此处将short*强制转换为int*,造成出错
    int* val = (int *)get_foo_c();
    printf("val: %d\n", *val);
}

// case 3 end
//////////////////////////////////////////////////////////////

/// case 4

void case4()
{
    char* str = "01234567";
    unsigned* u = (unsigned *)(str+1);
    printf("0x%08x\n", *u);
}

/// case 4 end

int main()
{
    printf("test of alignment trap...\n");

//foolish();

//case2();
    //case3();
    case4();

return 0;
}

以下是在某ARMLinux平台下的测试结果,依次将错误处理等级设置为0到5,出现不的结果,如下:

# echo 0 >  /proc/cpu/alignment 
# ./a.out 
test of alignment trap...
0x30333231
# echo 1 >  /proc/cpu/alignment 
# ./a.out 
testAlignment trap: a.out (1125) PC=0x000086c8 Instr=0xe5931000 Address=0x00008961 FSR 0x001
 of alignment trap...
0x30333231
# echo 2 >  /proc/cpu/alignment 
# ./a.out 
test of alignment trap...
0x34333231
# echo 3 >  /proc/cpu/alignment 
# ./a.out 
testAlignment trap: a.out (1127) PC=0x000086c8 Instr=0xe5931000 Address=0x00008961 FSR 0x001
 of alignment trap...
0x34333231
# echo 4 >  /proc/cpu/alignment 
# ./a.out 
test of alignment trap...
Bus error
# echo 5 >  /proc/cpu/alignment 
# ./a.out 
testAlignment trap: a.out (1129) PC=0x000086c8 Instr=0xe5931000 Address=0x00008961 FSR 0x001
 of alignment trap...
Bus error

常用的是使用等级3来处理,即提示错误并进行修复。

上面只讲到如何使用代码出现字节对齐错误,但没涉及如何排查问题。示例代码十分简单,很容易定位错误地方,但如果在大型项目中,就很难定位,尤其是在嵌入
式中,——嵌入式的调试也相对比较困难、麻烦。以我的经验,与其用gdbserver来调试,不如靠经验及printf大法解决问题来得更快(当然,仅个
人看法)。

本来想用工具调试来发现出错的代码位置,但尝试了,没结果。

在代码编写中,需要注意一下以下的事:
1、结构体尽量使用4字节对齐,比如设置一个传输长度len的类型时,用short表示的范围已经足够,当然也可以用int。像制定一些网络协议,最好考虑一下4字节对齐。
2、分配内存时也尽量4字节对齐,无论是申请的内存还是定义数组大小。
3、对指针进行访问的时候也要十分注意4字节对齐,特别是一些为了避免编译警告的强制类型转换。

参考资料:

http://www.rt-embedded.com/blog/archives/resolving-alignment-traps/
http://simplemachines.it/arm-linux/book/afaq.html

迟 代码随笔 即日

ARMLinux下Alignment trap的一些测试 【转自 李迟的专栏 CSDN http://blog.csdn.net/subfate/article/details/7847356的更多相关文章

  1. Alignment trap 解决方法  【转 结合上一篇

    前几天交叉编译crtmpserver到arm9下.编译通过,但是运行的时候,总是提示Alignment trap,但是并不影响程序的运行.这依然很令人不爽,因为不知道是什么原因引起的,这就像一颗定时炸 ...

  2. coreseek实战(一):windows下coreseek的安装与测试

    coreseek实战(一):windows下coreseek的安装与测试 网上关于 coreseek 在 windows 下安装与使用的教程有很多,官方也有详细的教程,这里我也只是按着官方提供的教程详 ...

  3. linux下开发板网络速度测试记录

        由于做的项目对于网络和USB的读写速度有很高的要求,因此新拿回来的板子要测试网络和usb的最佳传输速度.要考虑不少因素,先把我能想到的记录下来.     测试的环境是开发板和ubuntu虚拟机 ...

  4. ubuntu下opencv2.4.9安装测试

    ubuntu下opencv2.4.9安装测试 whowhoha@outlook.com 一.依赖包安装 1.  build-essential 软件包 sudo apt-get install bui ...

  5. mosquitto在Linux环境下的部署/安装/使用/测试

    mosquitto在Linux环境下的部署 看了有三四天的的源码,(当然没怎么好好看了),突然发现对mosquitto的源码有了一点点感觉,于是在第五天决定在Linux环境下部署mosquitto. ...

  6. Tomcat免安装版的环境变量配置以及Eclipse下的Tomcat配置和测试

    Tomcat是目前比较流行的开源且免费的Web应用服务器,在我的电脑上第一次安装Tomcat,再经过网上教程和自己的摸索后,将这个过程 重新记录下来,以便以后如果忘记了可以随时查看. 注意:首先要明确 ...

  7. [原创]MinHook测试与分析(x64下 E9,EB,CALL指令测试,且逆推测试微软热补丁)

    依稀记得第一次接触Hook的概念是在周伟民先生的书中-><<多任务下的数据结构与算法>>,当时觉得Hook很奇妙,有机会要学习到,正好近段日子找来了MiniHook,就一 ...

  8. win10下caffe安装与mnist测试实验注意点

    caffe安装 安装内容:win10教育版+anaconda2+python(无gpu版本) 安装教程:主要依照三年一梦教程:https://www.cnblogs.com/king-lps/p/65 ...

  9. linux环境下使用jmeter进行压力测试

    linux环境下使用jmeter进行压力测试 linux环境下使用就meter进行压力测试: linux环境部署: 在Linux服务器先安装jdk: 2.以jdk-8u172-linux-x64.ta ...

随机推荐

  1. Tomcat7.0安装配置

    很久没有通过博客对学习所得进行记录了. 现在将使用Tomcat的一些经验和心得写到这里,作为记录和备忘.如果有朋友看到,也请不吝赐教. 首先,我个人使用的是apache-tomcat-7.0.27你可 ...

  2. 解决Maven的Could not update project XXX configuration NullPointerException 错误

    1. 从eclipse删除这个项目,但不要从磁盘删除: 2. 关闭eclipse: 3. 删除项目目录下的:.settings目录: 4. 删除项目目录下的:.projects目录: 5. 删除项目目 ...

  3. 在eclipse中用gradle搭建MapReduce项目

    我用的系统是ubuntu14.04新建一个Java Project. 这里用的是gradle打包,gradle默认找src/main/java下的类编译.src目录已经有了,手动在src下创建main ...

  4. VS中Qt的探索02

    边看C++ GUI QT4教程,边在VS2010中进行编程学习探索. 在使用Qt设计师时,其中每一个对象的ObjectName属性是非常重要的,在程序功能的实现过程中,需要不断的使用该变量名. 当所有 ...

  5. Image放大缩小在放进Imageview

    // 拿到要缩小放大的Bitmap obitmap = BitmapFactory.decodeResource(this.getResources(),R.drawable.ic_launcher) ...

  6. Android 自定义View

    Android 自定义View流程中的几个方法解析: onFinishInflate():从布局文件.xml加载完组件后回调 onMeasure() :调用该方法负责测量组件大小 onSizeChan ...

  7. 版本控制简介,git使用----使用GitHub托管代码

    关于版本控制: 很久以前,人们苦于对写过的代码进行版本的管理,经常过了一段时间想恢复原来写过的代码却又忘了不知道丢到哪儿去了,有的人用加上时间后缀来命名文件的方法,便于后期维护,但是这样做的麻烦也很大 ...

  8. 20169212《Linux内核原理及分析》第十二周作业

    格式化字符串漏洞实验 格式化字符串漏洞是由像 printf(user_input) 这样的代码引起的,其中 user_input 是用户输入的数据,具有 Set-UID root 权限的这类程序在运行 ...

  9. 深入浅出Mybatis系列(六)---objectFactory、plugins、mappers简介与配置

    上篇文章<深入浅出Mybatis系列(五)---TypeHandler简介及配置(mybatis源码篇)>简单看了一下TypeHandler, 本次将结束对于mybatis的配置文件的学习 ...

  10. Could not load file or assembly or one of its dependencies. 试图加载格式不正确的程序。

    当我把编译好的程序托管到IIS下后,访问时出现了以下问题,服务器环境是IIS 7,操作系统 Windows server 2008 r2 64位. 出现上述问题的原因是,所加载的程序集中有32位的,也 ...