赞
踩
最近在使用rk3588跑官方提供的yolov5模型demo,能够完成单张图片的目标检测,但是在运行视频流demo时,系统报错:
segmentation fault(core dumped)
此时没有再给出更多的报错信息,不太好debug,在网上阅读了一些博客现在整理一下。
在Linux下遇到程序异常退出或者中止,操作系统通常会把程序当前的工作状况存储在一个名为core的文件中,其中包含了程序运行时的内存、寄存器和堆栈指针等信息,格式为ELF,这个过程叫做coredump,又称作核心转储。
因此需要找到报错时生成的core文件,首先先查看coredump是否生效:
$ ulimit -a
...
-c: core file size (blocks) 0
...
0表示core文件大小限制为0,不允许写入,所以无法生成core文件,需要修改为正数大小或unlimited才可使coredump生效。
通过以下命令取消生成core文件的内存大小限制:
ulimit -c unlimited
上面对core文件的操作仅对当前生效,若需要永久生效,则要将相应操作写入/etc/profile
。
core文件默认存储在程序的工作目录,可以通过命令cat /proc/sys/kernel/core_pattern
查看。
找到文件/etc/sysctl.conf
,通过vim打开文件:
sudo vim /etc/sysctl.conf
移动光标至文件末尾,按 i 键进入编辑模式,此时可以修改文本。
在文件末尾加入信息,可以指定core文件的存储路径:
kernel.core_pattern=/dumpdir/core_%e_%p_%t
附上core文件的参数信息:
%p - insert pid into filename # 添加 pid
%u - insert current uid into filename # 添加当前 uid
%g - insert current gid into filename # 添加当前 gid
%s - insert signal that caused the coredump into the filename # 添加导致产生 core 的信号
%t - insert UNIX time that the coredump occurred into filename # 添加 core 文件生成时的 unix 时间
%h - insert hostname where the coredump happened into filename # 添加主机名
%e - insert coredumping executable name into filename # 添加命令名
按 esc 键,此时退出修改文本。
保存退出vim:
:wq
控制core文件的文件名中是否添加pid作为扩展:
echo "1" > /proc/sys/kernel/core_uses_pid
这一步可能会报错Permission denied,这是因为重定向符号 “>” 和 “>>” 也是 bash 的命令。sudo 只是让 echo 命令具有了 root 权限,但是没有让 “>” 和 “>>” 命令也具有root 权限,所以 bash 会认为这两个命令都没有写入信息的权限。
所以这里可以利用 “sh -c” 命令,它可以让 bash 将一个字串作为完整的命令来执行,这样就可以将 sudo 的影响范围扩展到整条命令。
sudo sh -c ‘echo "1" > /proc/sys/kernel/core_uses_pid’
/proc/sys/kernel/core_uses_pid
这个文件的值若为1,则无论是否配置%p,最后生成的core文件都会添加pid,可以用cat命令进行确认。
在Ubuntu20.04
系统下,执行完上述操作,会发现还是无法在指定目录生成core文件。查看core文件存储路径:
$ cat /proc/sys/kernel/core_pattern
|/usr/share/apport/apport %p %s %c %d %P %E
发现core文件存储路径并非自己设置的,而是由管道交给了一个apport的程序,通过查询可知其是Ubuntu官方为了自动收集错误,生成程序崩溃报告的一个服务,即apport.service。
关掉这个服务:
sudo service apport stop
使用sudo service apport start可以开启这个服务。
如果最后仍然没有生成core文件,同时报错时显示segmentation fault
,可以在gcc/g++编译时增加-g选项:
例如:cc -O2 -Wall -Wextra -g -c -o test_VIDIOC_ENUMSTD.o test_VIDIOC_ENUMSTD.c
至此报错segmentation fault(core dumped)
且成功生成core文件。
进入rk3588开发板中的视频流demo所在的文件夹,使用gdb工具利用生成的core文件进行debug
gdb ./rknn_yolov5_video_demo core.3099
这样就进入了 gdb core 调试模式。
追踪产生segmenttation fault的位置及代码函数调用情况:
(gdb) bt
就可以定位到代码具体的报错信息和位置。
我是在虚拟机上完成代码的交叉编译,再将可执行文件demo移到开发板中进行测试的,可以看到板子在运行demo没有找到对应的库,报错时显示的路径是对应的库在虚拟机中的路径,因此怀疑是交叉编译出的问题。目前考虑将编译过程移到开发板上进行。具体情况还有待更新。
退出:
(gdb) quit
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。