1.起因是在测试S1 upload clip遇到的问题.

经过排查,确认是KVS SDK 3.1.1的锅

2.这个问题的原因是发生非对齐地址访问

然后尝试了一下echo 2 >/proc/cpu/alignment (2:fixup), 发现并不能解决问题

3.经过以上尝试不行,所以接下来就要想想如何定位错误。

代码出现字节对齐错误,有些代码量很小,很容易定位错误地方,但如果在大型项目中,就很难定位,尤其是在嵌入式中——嵌入式的调试也相对比较困难、麻烦。以我的经验,与其用gdb来调试,不如靠经验及printf大法解决问题来得更快,但是这次由于是kvs 的SDK(代码量有些大),不是我们自己的code,所以依靠printf不太现实。

因为这个log打印是由于系统发送signal(SIGBUS)产生的。
所以我们理所应当的可以利用这个signal做一些事情。

我们要在程序有问题的地方, 让它中断, 然后印出 backtrace 来让 addr2line 反查. 因此, 我们分成以下三个步骤说明之.( 利用此方法,也可以用来捕捉 SIGSEGV (Segmentation Fault, 内存区段错误) 所发生的地方. 甚至是其他的 signal 发生时, 程序执行的位置.)

  1. 用 signal 让程序在有问题的地方中断
  2. 印出 backtrace
  3. 使用 addr2line 来解析其内容(addr2line -e 执行文件 -f 地址)

1.首先我们先将行为模式设为5
echo 5 > /proc/cpu/alignment
关于 User faults, 有以下 5 种设定,
0 - ignore (默认值)
1 – warn
2 - fixup
3 - fixup+warn
4 - signal
5 - signal+warn (我们需要这个)

2.印出 backtrace
这个部份, 需要利用 backtrace(). 如果 source code 分成很多 .c 或 .cpp 的话, 请找出main() 所在的那个 档案来增加以下的 code,

/* 此为 signal handler */
static void catch_sig(int sig) {
void *trace[128];
int n = backtrace(trace, sizeof(trace) / sizeof(trace[0]));
backtrace_symbols_fd(trace, n, 1);
exit(0);
}
/* 此函式指定 SIGBUS 的 handler 为 catch_sig() */
static void set_signals(void) {
struct sigaction act;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
act.sa_handler = catch_sig;
sigaction(SIGBUS, &act, NULL);
}
/* 在你的 main() 的前头, 呼叫 set_signals() */
int main() {
set_signals();:
:
}

编译时, 务必增加 -g -rdynamic 选项.

重新编译及执行后, 若发生 Alignment trap, kernel 会送给这个 process 一个 SIGBUS 的 signal, 而我们在 set_signal() 里, 设定了收到 SIGBUS 时要执行 catch_sig(), 而在 catch_sig() 里, 我们利用backtrace() 来 取得 stack frame 的地址之后, 用 backtrace_symbols_fd() 来印出比较 看得懂的信息

3.本来想着从以上的log中判断出出错的位置,但是无奈什么多余的log都没有。
这个时候再猜测,会不会是kernel的log没打印全,所以我将kernel里面“quiet”去掉(NT9852X),结果还是不行。。难道是编译选项-s为了降低文件大小将一些符号删除,或是strip的锅? 然后我又尝试去掉这两个地方,结果还是没有log产生。
所以addrline也没法用了

4.烦人,还是要GDB,

接着我去找nvt的SDK 里面的tool,看看GDB是否在里面,找到之后,解了半天的编译错误,终于得到了GDB,
执行./gdb sc_producer
然后输入"r",按回车
结果触发upload clip,接着打印出信息
我亲爱的bug终于定位到了。

5.DEBUG (尝试),解决方案

接着找到出错的地方,尝试把结构体用4字节对齐的方式编译,然后问题果然没了

6.补充

理解SIGBUS产生的原因

  1. 硬件故障,不用说,程序员最常碰上的肯定不是这种情形。
  2. Linux平台上执行malloc(),如果没有足够的RAM,Linux不是让malloc()失败返回,
    而是向当前进程分发SIGBUS信号。
    注: 对该点执怀疑态度,有机会可自行测试确认当前系统反应。
  3. 某些架构上访问数据时有对齐的要求,比如只能从4字节边界上读取一个4字节的
    数据类型。IA-32架构没有硬性要求对齐,尽管未对齐的访问降低执行效率。另外
    一些架构,比如SPARC、m68k,要求对齐访问,否则向当前进程分发SIGBUS信号。

SIGBUS与SIGSEGV信号一样,可以正常捕获。SIGBUS的缺省行为是终止当前进程并产
生core dump。
一般我们平时遇到SIGBUS时总是因为地址未对齐导致的,而SIGSEGV则是由于内存地址不合法造成的。

对于以上几点,我们作为coding debug的人员,理所应当的应该关注第三点
SIGBUS(Bus error)总线错误:
引起原因:意味着指针所对应的地址是有效地址,但总线不能正常使用该指针。几乎总是由于对未对齐的读或写引起的。它之所以称为总线错误是因为对未对齐的内存访问时,被阻塞的组件就是地址总线。

对齐(alignment)数据项只能存储在地址是数据项大小的整数倍的内存位置上,这样可以加速内存访问。如:访问一个8字节的double的数据时,地址只能是8的整数倍,所以存储一个double的地址只能是24,8008,但不能存储于地址1006因为它不能被8整除,只要保证这个原则,就可以保证一个原子项数据不会跨页或cache块的边界。这样也就加快了访问数据的时间。

SIGBUS和SIGSEGV也许是我们在平时遇到的次数最多的两个内存错误信号。内存问题一直是最令我们头疼的事情,弄清楚两个信号的发生缘由对我们很好的理解程序的运行是大有裨益的。

我们来看两段程序:

//testsigsegv.c
int main()
{char *pc = (char*)0x00001111;*pc = 17;
}//testsigbus.c
int main()
{int *pi = (int*)0x00001111;*pi = 17;
}

上面的代码那么的相似,我们也同样用gcc编译(加上-g选项,便于gdb调试;平台Solaris Sparc),执行结果也都是dump core。但通过GDB对core进行观察,你会发现细微的不同。第一个例子出的core原因是:Program terminated with signal 11, Segmentation fault. 而第二个例子的core则提示:Program terminated with signal 10, Bus error. 两者有什么不同呢?这两段代码的共同点都是将一个非法地址赋值给指针变量,然后试图写数据到这个地址。

testsigsegv.c中,0x00001111这个地址值被赋给了char *pc;也就是告诉CPU通过这个地址我们要存取一个字节的值,对于一个字节长度的数据,无所谓对齐,所以该地址通过对齐校验;并被放到地址总线上了。而在testsigbus.c里,0x00001111这个地址值被赋给了int *pi;也就是告诉CPU通过这个地址我们要存取一个起码4个字节的值,那么对于长度4个字节的对象,其存放地址起码要被4整除才可以,而0x00001111这个值显然不能满足要求,也就不能通过内存对齐的校验。也就是说SIGBUS这个信号在地址被放到地址总线之后被检查出来的不符合对齐的错误;而SIGSEGV则是在地址已经放到地址总线上后,由后续流程中的某个设施检查出来的内存违法访问错误。
(因为一个地址位只能存一个字节,一个四字节的变量需要四个地址位,地址存储往往是连续的四个地址,首地址作为定义地址。于是能被四整除方便后续的数据处理。)

7.在代码编写中,需要注意一下以下的事:

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

KVS SDK Alignment trap debug相关推荐

  1. Alignment trap

    遇到的问题: (题意请描述清楚) : 程序执行一段时间(不固定, 一分钟以下) 会出现Alignment trap: xxx(pid) PC=0x0001645 -.. 来自kernel的错误讯息, ...

  2. 32.全网最详细trap讲解,trap语法格式,信号和用途,最常用的信号,trap常用的命令,ctrl + c,信号屏蔽和恢复,trap -,debug,exit,return示例,三个综合案例

    文章目录 语法详解 trap格式 信号和用途 最常用的信号 trap常用的命令 示例 ctrl + c 示例 信号屏蔽和恢复 trap - 示例 debug示例 exit示例 return示例 综合案 ...

  3. ARMLinux下Alignment trap的一些测试

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

  4. Linux / alignment trap - not handling instruction..

    概述 开始编辑日期:2018年12月26号,后重新整理从富文本编辑器转移至Markdown编辑器. 问题描述:Long Long Ago 嵌入式应用程序在现场使用时,小频次出现异常黑屏(进程死,Lin ...

  5. QCC 单地址SDK 使用MDE debug时无log输出

    同样的环境,同样的开发板使用ADK6.4.X的SDK debug没什么问题 但是 切换到单地址的SDK后,log没了,把固件烧录到芯片里可以正常跑起来 从MDE输出的信息来看是某了中文字符解析错误 但 ...

  6. Linux Command trap 信号捕捉

    Linux Command trap 信号捕捉 文章目录 Linux Command trap 信号捕捉 1. 简介 2. 语法 3. 信号介绍 4. 常用信号 5. 命令 6. 实例 6.1 ctr ...

  7. 【Linux】一步一步学Linux——trap命令(229)

    00. 目录 文章目录 00. 目录 01. 命令概述 02. 命令格式 03. 常用选项 04. 其它说明 05. 参考示例 06. 附录 01. 命令概述 trap命令用于指定在接收到信号后将要采 ...

  8. iceman写的关于Debug API的文章,特别是关于CONTEXT结构的描述,有空再翻译(转贴)

    转自http://www.woodmann.com/fravia/iceman1.htm WIN32 - Inside Debug API ------------------------ (Thin ...

  9. 基于Amazon KVS 与 Amazon Rekognition Streaming Video Events实时视频检测方案

    前言 1.1 视频识别场景介绍 在居家安防监控领域,基于实时视频的移动检测,发现监控环境中人.宠物.包裹等的出现,并且能实时地将检测结果通知给身处任何地方的用户是其重要的应用场景之一.但在这一场景的技 ...

最新文章

  1. css中.和#的区别 不写时代表什么
  2. addslashes 及 其他 清除空格的方法是不安全的
  3. 妙用Windows安全模式执行杀毒
  4. python pandas读取csv_Python3 pandas怎么读取csv文件的第一行的
  5. 与NWBC相关的服务器端配置
  6. 【三种解法】剑指 Offer 06. 从尾到头打印链表【附完整可运行代码】
  7. [渝粤教育] 广东-国家-开放大学 21秋期末考试招投标与合同管理10217k2 (2)
  8. CentOS卸载OpenJDK并安装Sun JDK
  9. 服务器实际显示内存,服务器实际显示内存
  10. 搜狐畅游一面(c++)
  11. Coin3D三维可视化教程3
  12. mac book 专用最新款win10镜像
  13. Landsat8遥感数据大气校正
  14. P3239 [HNOI2015]亚瑟王
  15. 教你做网线,呵呵。。
  16. 多线程有几种实现方法?同步有几种实现方法
  17. 江苏大学计算机考研上岸分享
  18. csdn下载积分兑换网址
  19. OpenStack落地德国大众:锐意创新还是孤注一掷?
  20. git ls-files:项目文件码数行数统计

热门文章

  1. Unity内存管理的原理
  2. 仿冒应用成新型诈骗手段 社交类应用中毒最深
  3. 信息系统基本知识(六)
  4. Unity技术手册 - 粒子基础主模块属性-中
  5. win10系统如何清理c盘垃圾
  6. 智能设备点巡检系统,快速提高设备管理效率,欢迎在线试用
  7. OpenNI 2.0
  8. qlikview连接数据库
  9. 思想的沉淀,精辟,杨澜如是说
  10. 十大网页设计者必看的网站