一次linux中定位c++程序运行异常的经历

简介: 一次linux中定位c++程序运行异常的经历

今天下午我遇到了一些棘手的问题,因为在mips64上编译程序,经常出现程序编译不出来,或者运行不正常,花了很长的时间定位,最后和同事一些解决了,下面分享出来我提炼出来的一些核心定位问题的步骤。


子线程创建不出来


猜测:go的程序都能创建出子线程,但是c++的创建不出来,但是在 x86 可以,是不是什么 linux 系统限制?

aHR0cHM6Ly9jb2RpbmczbWluLm9zcy1hY2NlbGVyYXRlLmFsaXl1bmNzLmNvbS8yMDIwLzA1LzI1L05qVUZtZTIyNDgucG5n.png


aHR0cHM6Ly9jb2RpbmczbWluLm9zcy1hY2NlbGVyYXRlLmFsaXl1bmNzLmNvbS8yMDIwLzA1LzI1L2xiRDBDYzIyNTAucG5n.png


解决方法:加错误日志进行调试(最 lower 办法)

找到报错点:


aHR0cHM6Ly9jb2RpbmczbWluLm9zcy1hY2NlbGVyYXRlLmFsaXl1bmNzLmNvbS8yMDIwLzA1LzI1LzBIZGNsWjIyNTEucG5n.png


查询 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


查询 linux 报错码含义, 得知错误码 22 果然和 man 手册中说的一致,是参数有问题。


aHR0cHM6Ly9jb2RpbmczbWluLm9zcy1hY2NlbGVyYXRlLmFsaXl1bmNzLmNvbS8yMDIwLzA1LzI1L3V5TXJvMTIyNTUucG5n.png


第一次尝试:扩大线程栈到上面说的 16384 ,但还是报错


aHR0cHM6Ly9jb2RpbmczbWluLm9zcy1hY2NlbGVyYXRlLmFsaXl1bmNzLmNvbS8yMDIwLzA1LzI1L2pVUWlUNzIzMDEucG5n.png

根据经验,查看最小页大小,发现是 16k , 而 x86 架构是 4K ,原来用的 20K 是不对齐的,怪不得创建不出来线程。

aHR0cHM6Ly9jb2RpbmczbWluLm9zcy1hY2NlbGVyYXRlLmFsaXl1bmNzLmNvbS8yMDIwLzA1LzI1L1ZDbVhVUDIzMDMucG5n.png

依次尝试, 最终发现 10*16K 子线程成功创建。


但是不准确,按其说法,应该是设置 PAGESIZE 的整数倍都行,怀疑其对最小值有要求。 c++ 的头文件在 /usr/include 目录下面, PTHREAD_STACK_MIN 是一个常量,估计里面会有定义,尝试查找

$ grep -rl PTHREAD_STACK_MIN *
bits/local_lim.h
pthread.h

还真让我找到了, 根据英文注释,至少要两个 64K 作为线程栈,才能跑起一个线程。

aHR0cHM6Ly9jb2RpbmczbWluLm9zcy1hY2NlbGVyYXRlLmFsaXl1bmNzLmNvbS8yMDIwLzA1LzI1LzFBWkZPVjIzMTEucG5n.png


至此问题解决。


部分线程卡住


我发现程序虽然正常运行,但是部分功能不正常,经过查看日志发现,有一个线程只执行了一半就卡住了。


经过查看日志可以定位出是哪个线程卡住,如果从日志看不出来也没关系。可以使用 pstack 进程号 看一些进程堆栈。


查看进程 pid


ps -ef |grep 进程名


使用 gdb 查看是否出现问题,两个重要命令


gdb attach {pid} #查看正在运行程序的栈
info thread #进入以后使用,查看线程信息


找到错误位置,出现了 fgets() 和 read() 函数,怀疑是此处出现问题。


image.png



aHR0cHM6Ly9jb2RpbmczbWluLm9zcy1hY2NlbGVyYXRlLmFsaXl1bmNzLmNvbS8yMDIwLzA1LzI1LyVFNCVCQyU4MSVFNCVCOCU5QSVFNSVCRSVBRSVFNCVCRiVBMSVFNiU4OCVBQSVFNSU5QiVCRV9mNmZmMGUyMi0xYzUwLTQ1OGMtODZmYi0zY2VkYjAwYTYyOTUyMzI4LnBuZw.png


怀疑 1: _LINE_LENGTH 1024 长度太短,接受命令返回值后超过了数组本身的长度,覆盖了位置的内存。


这种情况我以前遇到过,表现应该是程序直接就崩溃了。


怀疑 2:执行命令的时候卡了,导致后面的程序没有执行。


根据 gdb 打印出来的参数,执行 linux 命令进行测试,果然是卡在这了!


再次使用 pstree -p {pid} 查看,确实主线程,调用了 linux 命令卡住。


aHR0cHM6Ly9jb2RpbmczbWluLm9zcy1hY2NlbGVyYXRlLmFsaXl1bmNzLmNvbS8yMDIwLzA1LzI1LyVFNCVCQyU4MSVFNCVCOCU5QSVFNSVCRSVBRSVFNCVCRiVBMSVFNiU4OCVBQSVFNSU5QiVCRV9lZThiZTVhNC02MzEzLTQ5YTktOTY4Yy04NTYzZDljM2U5Y2QyMzM0LnBuZw.png


接下来解决卡命令的问题

解决 1:加 timeout 处理空返回。下面是示例命令,并不是我使用的命令。


timeout 5 ls -al


代表超过 5 秒返回。

解决 2:定位为什么这个 linux 命令会卡住。


strace ls -al



直到解决为止。这就是今晚我加班到 10 点 30 解决的问题,我又用了一个小时总结下整个过程备忘,希望对你也有帮助。

相关实践学习
通过日志服务实现云资源OSS的安全审计
本实验介绍如何通过日志服务实现云资源OSS的安全审计。
相关文章
|
6月前
|
安全 编译器 C++
C++异常详细介绍
C++异常详细介绍
370 10
|
安全 程序员 编译器
【C++】异常
C++异常处理机制允许在程序运行时出现错误时,通过`try`、`catch`和`throw`关键字将错误信息传递回调用栈,进行异常处理。它支持异常的重新抛出、自定义异常体系以及标准库提供的异常类层次结构,如`std::exception`及其派生类。异常处理提高了代码的健壮性和可维护性,但也带来了性能开销和代码复杂性等问题。合理使用异常机制,可以有效提升程序的稳定性和安全性。
309 3
|
7月前
|
XML 缓存 Linux
在Linux环境下解决Visual Studio Code字体显示异常和字体替换方法。
解决Linux下VS Code字体显示异常,需要对Linux字体渲染机制有所理解,并对VS Code的配置选项进行合理设置。替换字体时则要通过系统字体配置或VS Code设置来完成。通过上述方法,可以有效地解决字体显示问题,从而提升代码编辑的视觉体验。
1066 0
|
8月前
|
存储 监控 算法
基于跳表数据结构的企业局域网监控异常连接实时检测 C++ 算法研究
跳表(Skip List)是一种基于概率的数据结构,适用于企业局域网监控中海量连接记录的高效处理。其通过多层索引机制实现快速查找、插入和删除操作,时间复杂度为 $O(\log n)$,优于链表和平衡树。跳表在异常连接识别、黑名单管理和历史记录溯源等场景中表现出色,具备实现简单、支持范围查询等优势,是企业网络监控中动态数据管理的理想选择。
221 0
|
11月前
|
安全 Linux
阿里云linux服务器使用脚本通过安全组屏蔽异常海外访问ip
公网网站可能会遭受黑客攻击导致访问异常,使用此脚本可以屏蔽掉异常IP 恢复访问。也可自行设置定时任务定期检测屏蔽。
781 28
|
消息中间件 Linux C++
c++ linux通过实现独立进程之间的通信和传递字符串 demo
的进程间通信机制,适用于父子进程之间的数据传输。希望本文能帮助您更好地理解和应用Linux管道,提升开发效率。 在实际开发中,除了管道,还可以根据具体需求选择消息队列、共享内存、套接字等其他进程间通信方
349 16
|
Ubuntu Linux Go
golang编译成Linux可运行文件
本文介绍了如何在 Linux 上编译和运行 Golang 程序,涵盖了本地编译和交叉编译的步骤。通过这些步骤,您可以轻松地将 Golang 程序编译成适合 Linux 平台的可执行文件,并在目标服务器上运行。掌握这些技巧,可以提高开发和部署 Golang 应用的效率。
2558 14
|
机器学习/深度学习 人工智能 Ubuntu
|
Linux 开发工具 数据安全/隐私保护
linux异常一:feng 不在 sudoers 文件中,此事将被报告。yum提示Another app is currently holding the yum lock; waiting for
这篇文章介绍了在CentOS 7系统中安装Docker时遇到的两个常见问题及其解决方法:用户不在sudoers文件中导致权限不足,以及yum被锁定的问题。
315 2
linux异常一:feng 不在 sudoers 文件中,此事将被报告。yum提示Another app is currently holding the yum lock; waiting for
|
监控 Ubuntu Linux
使用VSCode通过SSH远程登录阿里云Linux服务器异常崩溃
通过 VSCode 的 Remote - SSH 插件远程连接阿里云 Ubuntu 22 服务器时,会因高 CPU 使用率导致连接断开。经排查发现,VSCode 连接根目录 ".." 时会频繁调用"rg"(ripgrep)进行文件搜索,导致 CPU 负载过高。解决方法是将连接目录改为"root"(或其他具体的路径),避免不必要的文件检索,从而恢复正常连接。