日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Native崩溃说明 so库崩溃、SIGBUS(bad memory access) 和 SIGSEGV(Invalid memory reference)

發布時間:2024/3/26 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Native崩溃说明 so库崩溃、SIGBUS(bad memory access) 和 SIGSEGV(Invalid memory reference) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

參考:友盟 : Native崩潰說明

一、概念說明

在應用崩潰的時候,我們將會獲取到兩個信息:

  • signal: 信號量,下文將會詳細的說明不同的信號量及其含義

  • code: 錯誤碼, 除了幾個所有信號量(signal) 公共的錯誤碼(code),一般不同信號量(signal)有特定的錯誤碼(code),可以看做是信號量(signal)的補充說明。

二、信號量(signal) 和 錯誤碼(code)說明

本節只介紹與崩潰相關的幾個 signal(CrashSDK 捕獲的 signal)及相關 code 的說明,更多內容見后面的參考文獻或網上找資料了解。

1. SIGILL

SIG是信號名的通用前綴,ILL是 illegal instruction( 非法指令 ) 的縮寫。

對應的數值為 4。

SIGILL 是當一個進程嘗試執行一個非法指令時發送給它的信號。

常見原因有:

  • CPU架構不匹配
  • .so 文件被破壞,或者代碼段被破壞導致;
  • 主動崩潰,如 _builtintrap() 也會使用非法指令來實現。

si_addr 為出錯的指令。

該信號量中常見的錯誤碼說明:

Code說明
ILL_ILLOPC非法的操作碼(opcode)
ILL_ILLOPN非法的操作數(operand)
ILL_ILLADR非法的尋址模式
ILL_ILLTRP非法的trap
ILL_PRVOPC特權操作碼(Privileged opcode)
ILL_PRVREG特權寄存器(Privileged register)
ILL_COPROC協處理器錯誤
ILL_BADSTK內部堆棧錯誤

2. SIGBUS

SIG是信號名的通用前綴,BUS是bus error (總線錯誤 ) ,意味著系統檢測到硬件問題后發送給進程的信號。

對應的數值為7。

通常該信號的產生不是因為硬件有物理上的損壞,而是代碼實現有 bug 導致 ,如地址不對齊,或者不存在的物理地址等。

si_addr 為所訪問的非法地址。

該信號量中常見的錯誤碼說明:

Code說明
BUS_ADRALN訪問的地址不對齊。32位處理器一般要求指針是4字節對齊的
BUS_ADRERR訪問不存在的物理地址。一般是由于 mmap 的文件發生 truncated 導致。常見于文件訪問過程中,被刪除或者替換;或 mmap 到內存后,繼續向文件寫入且導致文件 truncated,再讀取時就會出現該錯誤;另外, mmap 且訪問超過文件實際大小的空間時,也可能會出現該錯誤
BUS_OBJERR特定對象的硬件錯誤
BUS_MCEERR_ARBUS_MCEERR_AR
BUS_MCEERR_AQBUS_MCEERR_AQ

參考:淺談CPU內存訪問要求對齊的原因

SIGBUS(BUS_ADRALN) 解決方案:

在POSIX兼容的平臺上, bus error (總線錯誤) 是系統檢測到硬件問題后發送給進程的信號,但是通常該信號的產生不是因為硬件有物理上的損壞,更多的還是程序 bug 導致的。

總線錯誤幾乎總是由于對未對齊的讀或寫引起的。它之所以稱為總線錯誤是因為對未對齊的內存訪問時,被阻塞的組件就是地址總線。

對齊(alignment)數據項只能存儲在地址是數據項大小的整數倍的內存位置上,這樣可以加速內存訪問。如:訪問一個8字節的double的數據時,地址只能是8的整數倍,所以存儲一個double的地址只能是24,8008,但不能存儲于地址1006因為它不能被8整除,只要保證這個原則,就可以保證一個原子項數據不會跨頁或cache塊的邊界。

引起總線錯誤的示例:

union {char a[10];int i; }u;int *p =(int*)&(u.a[1]);*p =17;/*p中未對齊的地址將會引起總線錯誤*/

因為數組和int的聯合確保了a是按照int的4字節來對齊的,所以“a+1”肯定不是int來對齊的。

3. SIGSEGV

SIG 是信號名的通用前綴, SEGV 是 segmentation violation 的縮寫。

對應的數值為 11。

該信號意味著一個進程執行了一個無效的內存引用,或發生段錯誤。

si_addr 為所訪問的無效地址。

該信號量中常見的錯誤碼說明:

Code說明
SEGV_MAPERR地址不在 /proc/self/map 映射中
SEGV_ACCERR沒有訪問權限

SIGSEGV(SEGV_MAPERR) 解決方案 :

SIG 是信號名的通用前綴, SEGV 是 segmentation violation 的縮寫

在 POSIX 兼容的平臺上,SIGSEGV 是當一個進程執行了一個無效的內存引用,或發生段錯誤時發送給它的信號。SIGSEGV 的符號常量在頭文件 signal.h 中定義。因為在不同平臺上,信號數字可能變化,因此符號信號名被使用。通常,它是信號11。

對于不正確的內存處理,如當程序企圖訪問 CPU 無法定址的內存區塊時,計算機程序可能拋出 SIGSEGV。操作系統可能使用信號棧向一個處于自然狀態的應用程序通告錯誤,由此,開發者可以使用它來調試程序或處理錯誤。
在一個程序接收到 SIGSEGV 時的默認動作是異常終止。這個動作也許會結束進程,但是可能生成一個核心文件以幫助調試,或者執行一些其他特定于某些平臺的動作。
SIGSEGV可以被捕獲。也就是說,應用程序可以請求它們想要的動作,以替代默認發生的動作。這樣的動作可以是忽略它、調用一個函數,或恢復默認的動作。在一些情形下,忽略 SIGSEGV 導致未定義行為。
一個應用程序可能處理SIGSEGV的例子是調試器,它可能檢查信號棧并通知開發者目前所發生的,以及程序終止的位置。

SIGSEGV通常由操作系統生成,但是有適當權限的用戶可以在需要時使用kill系統調用或kill命令(一個用戶級程序,或者一個shell內建命令)來向一個進程發送信號。

  • 閃退場景一:recorder deleteRecording 之前 先判斷文件是否存在,否則會造成過度釋放,解決方法:
if ([[NSFileManager defaultManager] fileExistsAtPath:self.recorder.url.path]) {if (![self.recorder deleteRecording])NSLog(@"Failed to delete %@", self.recorder.url); }
  • 閃退場景二: delegate = nil 。

將XXViewContrller設置為delegate時,當頁面發生跳轉時,XXViewController的對象會被釋放,這是代碼走到[_delegate callbackMethod],便出現crash。
解決方法有二:
1.將@property (nonatomic ,assign) id <BLELibDelegate>delegate; 中 assign關鍵字改為weak。
2.在XXViewController的delloc方法中添加:xxx.delegate = nil;

4. SIGFPE

SIG是信號名的通用前綴。FPE是floating-point exception(浮點異常)的首字母縮寫拼接而成。

對應的數值為 8。

該信號一般是算術運算相關問題導致的。

si_addr 為失敗的指令。

該信號量中常見的錯誤碼說明:

Code說明
FPE_INTDIV整數除以 0
FPE_INTOVF整數溢出
FPE_FLTDIV浮點數除以 0
FPE_FLTOVF浮點數向下溢出
FPE_FLTRES浮點數結果不精確
FPE_FLTINV無效的浮點運算
FPE_FLTSUB下標超出范圍

5. SIGABRT

SIG是信號名的通用前綴。ABRT是abort program的縮寫。

對應的數值為 6。

該信號意味著異常退出;通常是調用 abort(), raise(), kill(), pthread_kill() 或者被系統進程殺死時出現。

當錯誤碼為 SI_USER 時表示是被其它程序殺死,一般情況是由于ANR被 system_server 殺死;

其他錯誤碼一般是業務自己調用 abort() 等函數退出,此時錯誤碼一般認為無效。

解決方案 :

abort program
SIG是信號名的通用前綴。ABRT是abort program的縮寫。

當操作系統發現不安全的情況時,它能夠對這種情況進行更多的控制,必要的話,它能要求進程進行清理工作。在調試造成此信號的底層錯誤時,并沒有什么妙招。 如 cocos2d 或 UIKit 等框架通常會在特定的前提條件沒有滿足或一些糟糕的情況出現時調用 C 函數 abort (由它來發送此信號)。

如果是iOS系統:
發生在UIApplication WillTerminate 時,是主動退出應用時發生的,所以對用戶沒什么實際影響。
iOS10訪問相冊時發生,目前只發生在iOS10+系統,需要修改工程plist文件,加入訪問權限提示信息。
補充:iOS 10 has updated privacy policy and implemented new privacy rules. You have to update your Info.plist app with this following fields by authorisation asked.

6. SIGSTKFLT

SIG是信號名的通用前綴,STKFLT是stack fault 的縮寫。

對應的數值為 16。

按照官方文檔說明,該信號量意味著協處理器棧故障。

根據網上的部分問題結論說明,在內存耗盡時,一般 malloc 返回 NULL 且設置 errno 為 ENOMEM,但有些系統可能會使用 SIGSTKFLT 信號代替。

7. SIGPIPE

該信號對應的數值為 13。

該信號意味著管道錯誤,通常在進程間通信產生,比如采用FIFO(管道)通信的兩個進程,讀管道沒打開或者意外終止仍繼續往管道寫,寫進程就會收到 SIGPIPE 信號。

8. SIGUSR2

為 12。用戶自定義信號2。

9. SIGTERM

SIG是信號名的通用前綴,TERM 是 Termination 的縮寫。該信號對應的數值為 15。

與 SIGKILL (signal 9) 類似,不過 SIGKILL 不可捕獲,而 SIGTERM 可被捕獲。一般常見于 APP 處于后臺時,被系統 vold 進程使用 SIGTERM 殺死,該情形基本沒有意義,可忽略。

另外,chromium 多進程架構中,經常也會使用 SIGTERM 殺死出現了異常的子進程。

10. SIGSYS

該信號對應的數值為 31,通常是因為無效的 linux 內核系統調用而產生。

在 android O (android 8.0) 中,部分不安全的系統調用被移除,若代碼中仍然使用它們,則會出現 SIGSYS。

11. SIGTRAP

該信號對應的數值為 5。gdb 調試設置斷點等操作使用的信號。

Code說明
TRAP_BRKPTTRAP_BRKPT
TRAP_TRACETRAP_TRACE
TRAP_BRANCHTRAP_BRANCH
TRAP_HWBKPTTRAP_HWBKPT

解決方案

SIG是信號名的通用前綴。TRAP 是陷阱的意思。它并不是一個真正的崩潰信號。它會在處理器執行 trap 指令時發送。LLDB調試器通常會處理此信號,并在指定的斷點處停止運行。如果你收到了原因不明的 SIGTRAP,先清除上次的輸出,然后重新進行構建通常能解決這個問題。

該異常是由于打算給一個附加的調試器在執行特定的斷點來中斷進程時觸發。你可以在自己的代碼中使用__builtin_trap()方法來觸發此異常。如果沒有被調試器所附加,那么進程將會結束并且生成一份崩潰報告。

如果Swift代碼在運行時發現一個意外的情況時,也會以該異常類型結束程序。例如:

為一個非可選(non-optional)類型被賦值nil
一個有問題的強制類型轉換

總結

以上是生活随笔為你收集整理的Native崩溃说明 so库崩溃、SIGBUS(bad memory access) 和 SIGSEGV(Invalid memory reference)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。