我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C++的异常机制导致的crash问题

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C++的异常机制导致的crash问题

问题背景

最近工作中遇到了一个非常奇怪的crash问题,反反复复分析了好久。由于保密原因,这里只记录一下分析思路,不会涉及到代码。

初步log分析

tombstone显示这是一个abort:Cmdline: /vendor/bin/hw/vendor.qti.camera.provider@2.7-service_64pid: 1189, tid: 20934, name: HwBinder:1189_5 >>> /vendor/bin/hw/vendor.qti.camera.provider@2.7-service_64 <<

第一反应是通过addr2line找到异常发生的点:

 addr2line -Cife out/target/product/zeus/symbols/vendor/lib64/hw/camera.qcom.so 0000000000eb2190 ~MiTrackerNode vendor/qcom/proprietary/camx-common/../camx/class="lazy" data-src/swl/mitrackaf/camxmitrackafnode.cpp:229 (discriminator 8) 

 addr2line -Cife out/target/product/zeus/symbols/vendor/lib64/hw/camera.qcom.so 0000000000eb21ac ~MiTrackerNode vendor/qcom/proprietary/camx-common/../camx/class="lazy" data-src/swl/mitrackaf/camxmitrackafnode.cpp:175

解析地址,发现addr2line的结果指向了函数的两个括号处{}:

/// Node::~NodeMiTrackerNode::~MiTrackerNode(){ //175行    CamxResult result = CamxResultSuccess;     CAMX_LOG_VERBOSE(CamxLogGroupTracker,"m_algoInitFlag %d m_pMiTracker %p cameraId %d",            m_algoInitFlag,m_pMiTracker,m_cameraInfo.cameraId);    CamxTime exitstartTime;    CamxTime exitendTime;    OsUtils::GetTime(&exitstartTime);    if (pthread_join(m_hInitThread, NULL) != 0)    {        CAMX_LOG_INFO(CamxLogGroupTracker,"m_hInitThread dead already\n");    }   //       .................................   //OsUtils::GetTime(&exitendTime);    CAMX_LOG_VERBOSE(CamxLogGroupTracker, " ~MiTrackerNode time = %d ms",        (OsUtils::CamxTimeToMillis(&exitendTime) - OsUtils::CamxTimeToMillis(&exitstartTime)));} //229行

意思是第一行代码的执行就出了问题?听起来不太合理,看来addr2line不能帮忙定位到问题。

使用objdump分析

换到objdump看下这段代码到底有什么特别的地方,使得addr2line不能工作。以下是通过aarch64-linux-gnu-objdump.exe -D E:\log\camera.qcom.so | less定位到的出问题附近的汇编代码块:

根据上面的分析,分别对这几个地址做解码:

E:\log\camlog-1112150636>D:\tools\gcc-linaro-7.5.0-2019.12-i686-mingw32_aarch64-linux-gnu\bin\aarch64-linux-gnu-addr2line.exe -e E:\log\camera.qcom.so 0xeb2108
vendor/qcom/proprietary/camx-common/../camx/class="lazy" data-src/swl/mitrackaf/camxmitrackafnode.cpp:227 (discriminator 14)

E:\log\camlog-1112150636>D:\tools\gcc-linaro-7.5.0-2019.12-i686-mingw32_aarch64-linux-gnu\bin\aarch64-linux-gnu-addr2line.exe -e E:\log\camera.qcom.so 0xeb20c4
vendor/qcom/proprietary/camx-api/camx/utils/camxosutils.h:1518 (discriminator 4)

E:\log\camlog-1112150636>D:\tools\gcc-linaro-7.5.0-2019.12-i686-mingw32_aarch64-linux-gnu\bin\aarch64-linux-gnu-addr2line.exe -e E:\log\camera.qcom.so 0xeb20d8
vendor/qcom/proprietary/camx-api/camx/utils/camxosutils.h:1518 (discriminator 4)

E:\log\camlog-1112150636>D:\tools\gcc-linaro-7.5.0-2019.12-i686-mingw32_aarch64-linux-gnu\bin\aarch64-linux-gnu-addr2line.exe -e E:\log\camera.qcom.so 0xeb2150
vendor/qcom/proprietary/camx-common/../camx/class="lazy" data-src/swl/mitrackaf/camxmitrackafnode.cpp:?

指向的代码分别是这些:

static UINT32 CamxTimeToMillis(        CamxTime*   pTime){    return (pTime == NULL) ? 0 : ((1000 * pTime->seconds) + ((pTime->nanoSeconds) / 1000000L));//这行代码就是vendor/qcom/proprietary/camx-api/camx/utils/camxosutils.h:1518} /// MiTrackerNode::~MiTrackerNodeMiTrackerNode::~MiTrackerNode(){ //175行     OsUtils::GetTime(&exitendTime);    CAMX_LOG_VERBOSE(CamxLogGroupTracker, " ~MiTrackerNode time = %d ms",    //这行代码就是vendor/qcom/proprietary/camx-common/../camx/class="lazy" data-src/swl/mitrackaf/camxmitrackafnode.cpp:227        (OsUtils::CamxTimeToMillis(&exitendTime) - OsUtils::CamxTimeToMillis(&exitstartTime)));} //229行

由此可以推测,这个terminate的源头很可能就在这个CamxTimeToMillis的调用上。具体产生的原因暂不明了,但删除这行代码后,这个错误就消失了。

复现后继续分析

不久,问题再次复现,并且这一次现象变得更加奇怪了。

这一次的backtrace跟上一次一模一样:11-09 12:15:57.206 29142 29142 F DEBUG : pid: 12760, tid: 28582, name: HwBinder:12760_ >>> /vendor/bin/hw/vendor.qti.camera.provider@2.7-service_64 <<<11-09 12:15:57.207 29142 29142 F DEBUG : uid: 104711-09 12:15:57.207 29142 29142 F DEBUG : tagged_addr_ctrl: 000000000000000111-09 12:15:57.207 29142 29142 F DEBUG : signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr --------11-09 12:15:57.207 29142 29142 F DEBUG : Abort message: 'terminating with uncaught exception of type NSt6__ndk112system_errorE'11-09 12:15:57.207 29142 29142 F DEBUG : x0 0000000000000000 x1 0000000000006fa6 x2 0000000000000006 x3 0000007559da01a011-09 12:15:57.207 29142 29142 F DEBUG : x4 736f646277641f73 x5 736f646277641f73 x6 736f646277641f73 x7 7f7f7f7f7f7f7f7f11-09 12:15:57.208 29142 29142 F DEBUG : x8 00000000000000f0 x9 54725e8097ae4b13 x10 0000000000000000 x11 ffffff80ffffffdf11-09 12:15:57.208 29142 29142 F DEBUG : x12 0000000000000001 x13 000000007fffffff x14 000000000037366a x15 000000258cff67cb11-09 12:15:57.208 29142 29142 F DEBUG : x16 00000079b89f9060 x17 00000079b89d54e0 x18 000000752fcf4000 x19 00000000000031d811-09 12:15:57.208 29142 29142 F DEBUG : x20 0000000000006fa6 x21 00000000ffffffff x22 00000079b89fb350 x23 0000007559da031011-09 12:15:57.208 29142 29142 F DEBUG : x24 0000007559da02d0 x25 0000000000000048 x26 b4000078083bda60 x27 b4000078287262c011-09 12:15:57.208 29142 29142 F DEBUG : x28 b4000078287262c0 x29 0000007559da022011-09 12:15:57.208 29142 29142 F DEBUG : lr 00000079b898583c sp 0000007559da0180 pc 00000079b8985868 pst 000000000000100011-09 12:15:57.209 29142 29142 F DEBUG : backtrace:11-09 12:15:57.209 29142 29142 F DEBUG : #00 pc 0000000000051868 /apex/com.android.runtime/lib64/bionic/libc.so (abort+168) (BuildId: b15ac47006c5c2933d0526c330c56105)11-09 12:15:57.209 29142 29142 F DEBUG : #01 pc 000000000004911c /apex/com.android.vndk.v31/lib64/libc++.so (abort_message+252) (BuildId: 3800ebf760648abf274c4f36afc38008)11-09 12:15:57.209 29142 29142 F DEBUG : #02 pc 0000000000049310 /apex/com.android.vndk.v31/lib64/libc++.so (demangling_terminate_handler()+240) (BuildId: 3800ebf760648abf274c4f36afc38008)11-09 12:15:57.209 29142 29142 F DEBUG : #03 pc 0000000000049ecc /apex/com.android.vndk.v31/lib64/libc++.so (std::__terminate(void (*)())+16) (BuildId: 3800ebf760648abf274c4f36afc38008)11-09 12:15:57.209 29142 29142 F DEBUG : #04 pc 0000000000049e64 /apex/com.android.vndk.v31/lib64/libc++.so (std::terminate()+56) (BuildId: 3800ebf760648abf274c4f36afc38008)11-09 12:15:57.209 29142 29142 F DEBUG : #05 pc 00000000005afcf4 /vendor/lib64/hw/camera.qcom.so (__clang_call_terminate+12) (BuildId: 882d57000dbf93c8161629a99404f1c4)11-09 12:15:57.209 29142 29142 F DEBUG : #06 pc 0000000000f97fec /vendor/lib64/hw/camera.qcom.so (CamX::MiTrackerNode::~MiTrackerNode()+444) (BuildId: 882d57000dbf93c8161629a99404f1c4)11-09 12:15:57.209 29142 29142 F DEBUG : #07 pc 0000000000f98004 /vendor/lib64/hw/camera.qcom.so (CamX::MiTrackerNode::~MiTrackerNode()+20) (BuildId: 882d57000dbf93c8161629a99404f1c4)11-09 12:15:57.209 29142 29142 F DEBUG : #08 pc 0000000001082d10 /vendor/lib64/hw/camera.qcom.so (CamX::Node::Destroy()+5440) (BuildId: 882d57000dbf93c8161629a99404f1c4)

同样addr2line也是指向CamX::MiTrackerNode::~MiTrackerNode()的开头。所以addr2line对于这个问题也同样不好使。更糟糕的是,这一次连objdump也不好使了:

死磕问题

山穷水尽的情况下只能反过来思考,__clang_call_terminate这个函数在什么情况下会被调用到。opengrok一搜,调用这个函数的地方太多了。只好再看下这个abort发生前的log信息,下面几行log让我像突然触电一样:

11-09 12:15:51.979 12760 28582 W libc : invalid pthread_t (0) passed to pthread_join
11-09 12:15:52.067 12760 28582 E libc++abi: terminating with uncaught exception of type NSt6__ndk112system_errorE
11-09 12:15:52.206 12760 28582 F libc : Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 28582 (HwBinder:12760_), pid 12760 (vendor.qti.came)

第一行提示了pthread处出现了一个警告,紧接着出现一个关键字:uncaught exception,这不就是C++中的exception机制吗?当一个exception没有通过try catch捕获的时候,就会出现这种情况。

C++的exception机制包括这几部分:

  对于每个 catch 语句的存在,编译器会在其所在的函数末尾加上一些特殊信息,包括当前函数可以捕获的异常表,以及清理表(cleanup table)。在进行栈展开时,会调用 libstdc++ 提供的特殊函数(称为 personality routine),会检查栈上的所有函数哪个异常可以被捕获。如果其调用栈上没有任何一个函数安装了try-catch,那么就会转入默认的处理handler。

类的析构函数如果没有try-catch语句,编译器会自动在这个析构函数最后面放一个默认的处理handler,也就是terminate。在出现异常的时候,直接跳转到这个默认处理handler里面执行。这也是为什么在这一次的汇编代码里面看不到有地方跳转到terminate,偏偏又执行到这里的原因。

详细介绍:C++ 异常是如何实现的 - 知乎

到这问题就比较清晰了,MiTrackerNode::~MiTrackerNode函数内部某个地方很可能发生了exception,而这个函数又没有安装try-catch,这导致exception的默认处理方法terminate被执行了。所以要找到问题,就需要在这个函数里面安装一个try-catch预语句,涵盖整个析构函数。这样就可以轻易抓到exception发生的源头,从而解决问题。目前正在等待问题复现并做最终的解决方案。我的预感是离问题解决也就是一步之遥了。

来源地址:https://blog.csdn.net/weixin_42136255/article/details/129818919

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C++的异常机制导致的crash问题

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C++异常处理机制及常见问题分析

C++异常处理机制及常见问题分析引言:C++是一种强大的编程语言,它提供了异常处理机制来处理程序运行过程中的错误和异常情况。异常处理是一种控制流程的机制,用于在特定的条件下,将控制从当前执行点转移到另一个处理点。本文将介绍C++中的异常处理
2023-10-22

C++中的异常处理机制介绍

本篇内容介绍了“C++中的异常处理机制介绍”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!异常处理增强错误恢复能力是提高代码健壮性的最有力的途
2023-06-17

c++异常处理机制是怎么样的

这篇文章主要介绍了c++异常处理机制是怎么样的,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。当一个程序出现错误时,它可能的情况有3种:语法错误,运行时错误和逻辑错误。语法错误
2023-06-17

C++中常见的异常处理问题解决方法

C++中常见的异常处理问题解决方法,需要具体代码示例引言:在编写C++程序时,时常会遇到程序出现异常的情况,如除数为0、数组越界、空指针访问等等。这些异常会导致程序的崩溃或者产生不可预测的结果,为了增强程序的稳定性和可靠性,我们需要使用异常
2023-10-22

C++中异常处理问题的详细解析

C++中异常处理问题的详细解析引言:异常处理是现代编程语言中一个非常重要的概念,能够提供程序的健壮性和可读性。C++是一门强大的编程语言,也提供了异常处理的机制。本文将详细解析C++中的异常处理问题,并提供具体的代码示例。一、异常处理的概念
2023-10-22

Excel数据导入Mysql常见问题汇总:如何处理特殊字符导致导入失败的问题?

Excel数据导入MySQL常见问题汇总:如何处理特殊字符导致导入失败的问题?导入数据到MySQL是一个常见且重要的操作,但在实际操作中,你可能会遇到一些问题。其中之一就是特殊字符导致导入失败的情况。本文将为你介绍一些常见的问题及其解决方法
2023-10-22

C++ 函数返回值的异常处理机制

c++++ 函数的返回值在发生异常时未定义,需要通过 try-catch 块捕获异常并采取适当措施:仅在函数无法从错误中恢复时抛出异常。使用明确且有意义的异常类型。在函数文档中记录可能抛出的异常。使用 try-catch 块捕获异常并执行必
C++ 函数返回值的异常处理机制
2024-04-13

Xcode 10升级导致项目报错的常见问题解决

前言 前不久,伴随着iOS 12版本的发布,苹果升级了Xcode 版本,最新的版本是Xcode 10.1。不过升级后经常会遇到各种编译问题,下面就给大家总结一些常见的错误(我项目遇到的)。 话不多说了,来一起看看详细的介绍吧 library
2022-05-27

如何实现C++中的异常处理机制?

如何实现C++中的异常处理机制?引言:异常处理是编程中非常重要的一部分,它可以提高程序的可靠性和稳定性。在C++中,异常处理机制可以帮助我们处理程序中的错误和异常情况,使得程序的控制流能够在异常发生时进行变更,从而避免程序的崩溃。本文将介绍
如何实现C++中的异常处理机制?
2023-11-02

C++中常见的空指针异常问题解决方案

C++中常见的空指针异常问题解决方案引言:在C++编程中,空指针异常是一种常见的错误类型。当程序试图访问指向空地址的指针时,就会导致空指针异常的发生。在大型项目中,空指针异常可能会导致程序崩溃或产生不可预期的行为。因此,开发人员需要了解如何
2023-10-22

C语言异常处理机制的示例分析

这篇文章将为大家详细讲解有关C语言异常处理机制的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。异常处理机制:setjmp()函数与longjmp()函数  C标准库提供两个特殊的函数:setjmp
2023-06-20

详解C++中的异常和错误处理机制

在C++编程中,异常处理和错误处理机制是非常重要的,它们可以帮助程序员有效地处理运行时错误和异常情况,本文就来介绍一下C++中的异常处理和错误处理机制吧
2023-05-19

C++ 函数异常常见问题解答:解决开发中的难题

要解决 c++++ 函数异常问题,可遵循以下步骤:使用 try-catch 块或 noexcept 指定符处理异常。当函数确实不会引发任何异常时,才使用 noexcept。使用 throw 语句向上层函数传播异常。使用特定异常类来处理特定异
C++ 函数异常常见问题解答:解决开发中的难题
2024-05-02

C++嵌入式开发中的异常处理机制

c++++异常处理机制在嵌入式开发中至关重要,可处理超出预期的异常,确保系统稳定性。有两种异常类型:标准异常和用户定义异常,可使用throw抛出异常,使用try-catch捕获异常。实战案例展示异常处理在嵌入式应用程序中的应用,处理eepr
C++嵌入式开发中的异常处理机制
2024-05-11

如何解决磁盘写满导致MySQL复制失败的问题

小编给大家分享一下如何解决磁盘写满导致MySQL复制失败的问题,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!案例场景 今天在线上发现一个问题,由于监控没
2023-06-14

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录