对于c++程序来说,以segment fault为代表的程序异常行为千奇百怪,没有一套比较丰富的工具集去对付他们,在处理实际问题时就会显得捉襟见肘 。本文列举几种程序异常的定位方法 。
子线程创建不出来
猜测:go的程序都能创建出子线程,但是c++的创建不出来,但是在 x86 可以,是不是什么 linux 系统限制?
文章插图
解决方法:加错误日志进行调试(最 lower 办法)
【Linux定位c++程序运行异常的经历《实操》】找到报错点:
文章插图
查询 man 手册,看看是不是能找到有帮助的东西:
man pthread_attr_setstacksize
打印出解释:ERRORS pthread_attr_setstacksize() can fail with the following error: EINVAL The stack size is less than PTHREAD_STACK_MIN (16384) bytes.On some systems, pthread_attr_setstacksize() can fail with the error EINVAL if stacksize is not a multiple of the system page size.
翻译上面的话,可能会产生这个错误:- EINVAL 堆栈大小小于 PTHREAD_STACK_MIN(16384) 字节 。
- 在某些系统上,如果 stacksize 不是系统页面大小的倍数,pthread_attr_setstacksize() 可能会失败,并显示错误 EINVAL
文章插图
第一次尝试:扩大线程栈到上面说的 16384,但还是报错
文章插图
根据经验,查看最小页大小,发现是 16k , 而 x86 架构是 4K,原来用的 20K 是不对齐的,怪不得创建不出来线程 。
文章插图
依次尝试, 最终发现 10*16K 子线程成功创建 。
但是不准确,按其说法,应该是设置 PAGESIZE 的整数倍都行,怀疑其对最小值有要求 。c++ 的头文件在 /usr/include 目录下面,PTHREAD_STACK_MIN 是一个常量,估计里面会有定义,尝试查找
$ grep -rl PTHREAD_STACK_MIN *还真让我找到了, 根据英文注释,至少要两个 64K 作为线程栈,才能跑起一个线程 。
bits/local_lim.h
pthread.h
文章插图
我发现程序虽然正常运行,但是部分功能不正常,经过查看日志发现,有一个线程只执行了一半就卡住了 。
经过查看日志可以定位出是哪个线程卡住,如果从日志看不出来也没关系 。可以使用 pstack 进程号 看一些进程堆栈 。
查看进程 pid:
ps -ef |grep 进程名使用 gdb 查看是否出现问题,两个重要命令:
- gdb attach {pid} #查看正在运行程序的栈
- info thread #进入以后使用,查看线程信息
文章插图
怀疑 1:_LINE_LENGTH 1024 长度太短,接受命令返回之后超过了数组本身的长度,覆盖了未知的内存 。
这种情况我以前遇到过,表现应该是程序直接就崩溃了 。
怀疑 2:执行命令的时候卡了,导致后面的程序没有执行 。
根据 gdb 打印出来的参数,执行 linux 命令进行测试,果然是卡在这了!
再次使用 pstree -p {pid} 查看,确实主线程,调用了 linux 命令卡住 。
文章插图
接下来解决卡命令的问题 。
解决 1:加 timeout 处理空返回 。下面是示例命令,并不是我使用的命令 。
timeout 5 ls -al
代表超过 5 秒返回 。解决 2:定位为什么这个 linux 命令会卡住 。
strace ls -al
直到解决为止 。希望对大家也有帮助 。哪里写的不好大家可以评论区留言 大家一起学习交流一下推荐阅读
- 详解linux多线程——互斥锁、条件变量、读写锁、自旋锁、信号量
- Linux系统网络相关的常用命令集合
- Deepin Linux如何安装Terminus终端
- Linux高级命令
- 教你编译一个基于arm的Linux内核,并用qemu模拟器测试
- 教你编写你的第一个Linux 内核模块“hello_module”
- linux驱动开发第2讲:应用程序里的write如何调到驱动里的write?
- 软件测试基础——Linux系统搭建MySQL数据库
- 网店产品定位 淘宝的产品定位
- 怎么创建自己店铺的定位 店铺定位步骤哪4个步骤