在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::sptr const&)+540)
03 pc 0000000000016518 /system/lib64/libcesfwk_core.z.so(OHOS::EventFwk::CommonEvent::SubscribeCommonEvent(std::__1::shared_ptr const&)+468)
04 pc 0000000000012c20 /system/lib64/libcesfwk_innerkits.z.so(OHOS::EventFwk::CommonEventManager::SubscribeCommonEvent(std::__1::shared_ptr 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(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 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/lbcyllqj/article/details/143753425