鸿蒙5.0版开发:分析CppCrash(进程崩溃)

207 阅读3分钟

在HarmonyOS 5.0中,CppCrash指的是C/C++运行时崩溃,这类崩溃可能由空指针异常、数组越界异常、栈溢出异常等原因引起。系统提供了基于posix信号机制的崩溃异常检测能力,能够生成详细的故障日志以辅助故障定位。本文将详细介绍如何分析CppCrash,包括异常检测能力、崩溃问题定位分析思路,以及具体的案例分析。

CppCrash异常检测能力 进程崩溃基于posix信号机制,目前主要支持对以下崩溃异常信号的处理:

信号值(signo) 信号 解释 触发原因 4 SIGILL 非法指令 进程执行了非法、格式错误、未知或特权指令 5 SIGTRAP 断点或陷阱异常 异常或trap指令发生 6 SIGABRT 进程终止 进程异常终止,通常为进程自身调用abort()函数 7 SIGBUS 非法内存访问 进程访问了对齐或者不存在的物理地址 8 SIGFPE 浮点异常 进程执行了错误的算术运算,如除数为0、浮点溢出等 11 SIGSEGV 无效内存访问 进程访问了无效内存引用 16 SIGSTKFLT 栈错误 处理器执行了错误的栈操作,如栈空时弹出、栈满时压入 31 SIGSYS 错误的系统调用 系统调用时使用了错误或非法参数 以上部分故障信号,根据具体的场景还有二级分类(code)。

日志格式与获取 CppCrash故障根据报错场景可以分为运行态CppCrash故障和开发态CppCrash故障。在开发态下,DevEco Studio会收集CppCrash、App Freeze、JS Crash、System Freeze、ASan的崩溃日志到FaultLog下,开发者可以通过FaultLog的CppCrash日志、ASAN日志定位问题的具体原因。在运行态下,开发者需要提前开通崩溃服务,收集运行状态下的CppCrash。

基于崩溃栈定位行号 在应用开发场景中,对于应用自身的动态库,生成的cppcrash堆栈可以直接跳转到代码行处,支持Native栈帧和JS栈帧,无需开发者自行进行解行号操作。对于部分未能解析跳转到对应行号的栈帧,可以通过以下方式进行解析:

DevEco Studio开发者环境下,支持调用栈直接跳转到对应行号:在应用开发场景,对于应用自身的动态库,生成的cppcrash堆栈可以直接跳转到代码行处,支持Native栈帧和JS栈帧,无需开发者自行进行解行号操作。

使用addr2line工具:对于未能直接跳转的栈帧,可以使用addr2line工具将地址转换为代码行号。例如,使用以下命令:

$ addr2line -Cpie ./libcesfwk_core.z.so 000000000001c5a4 /mnt/disk/jenkins/ci/workspace/zidane_system_pipeline_release/compile/component_code/out/baltimore/../../base/notification/common_event_service/frameworks/core/src/common_event_proxy.cpp:385 这将帮助开发者快速定位到具体的代码行。

典型案例分析 锁范围不足导致的Crash问题 设备开关机压测时,崩溃在libcesfwk_core.z.so,崩溃栈如下:

Timestamp:1970-11-28 13:44:49.206 Pid:2906 Uid:10006 Process name:com.ohos.xxx Reason:Signal:SIGSEGV(SEGV_MAPERR)@0x00492e6b7766746e Fault thread Info: Tid:2978, Name:com.ohos.system #00 pc 000000000003fea8 /system/lib64/libipc_core.z.so(OHOS::PeerHolder::Remote()+12) #01 pc 000000000001c5a4 /system/lib64/libcesfwk_core.z.so(OHOS::EventFwk::CommonEventProxy::SendRequest(OHOS::EventFwk::ICommonEvent::Message, OHOS::MessageParcel&, OHOS::MessageParcel&)+168) #02 pc 000000000001cff8 /system/lib64/libcesfwk_core.z.so(OHOS::EventFwk::CommonEventProxy::SubscribeCommonEvent(OHOS::EventFwk::CommonEventSubscribeInfo const&, OHOS::sptrOHOS::IRemoteObject const&)+540) #03 pc 0000000000016518 /system/lib64/libcesfwk_core.z.so(OHOS::EventFwk::CommonEvent::SubscribeCommonEvent(std::__1::shared_ptrOHOS::EventFwk::CommonEventSubscriber const&)+468) #04 pc 0000000000012c20 /system/lib64/libcesfwk_innerkits.z.so(OHOS::EventFwk::CommonEventManager::SubscribeCommonEvent(std::__1::shared_ptrOHOS::EventFwk::CommonEventSubscriber const&)+56) #05 pc 000000000003253c /system/lib64/module/libcommonevent.z.so #06 pc 0000000000019808 /system/lib64/libace_napi.z.so(NativeAsyncWork::AsyncWorkCallback(uv_work_s*)+316) #07 pc 000000000001156c /system/lib64/libuv.so #08 pc 00000000000d02a0 /system/lib64/libc.so(__pthread_start(void*)+40) #09 pc 0000000000072128 /system/lib64/libc.so(__start_thread+68) ...

根据Reason可知为野指针,根据#01定位到具体的代码行有:

$ addr2line -Cpie ./notification/common_event_service/libcesfwk_core.z.so 000000000001c5a4 /mnt/disk/jenkins/ci/workspace/zidane_system_pipeline_release/compile/component_code/out/baltimore/../../base/notification/common_event_service/frameworks/core/src/common_event_proxy.cpp:385 对应的代码如下所示:

bool CommonEventProxy::SendRequest(ICommonEvent::Message code, MessageParcel &data, MessageParcel &reply) { EVENT_LOGD("start"); sptr remote = Remote(); if (remote == nullptr) { EVENT_LOGD("Remote is NULL, %{public}d", code); } MessageOption option(MessageOption::TF_SYNC); int32_t result = remote->SendRequest(static_cast<uint32_t>(code), data, reply, option); if (result != OHOS::NO_ERROR) { return false; } EVENT_LOGD("end"); return true; } 通过分析,可以发现remote指针可能为nullptr,导致后续的调用出现崩溃。

结语 通过本文的介绍,你应该对如何在HarmonyOS 5.0中分析CppCrash有了基本的了解。CppCrash分析是提升应用稳定性和用户体验的重要环节,合理利用日志分析和工具检测可以使你的应用更加健壮和易于维护。希望本文能够帮助你在开发过程中更好地分析和处理CppCrash问题。 ————————————————

                        版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                    

原文链接:blog.csdn.net/lbcyllqj/ar…