キャッチできない例外をキャッチする
@try @catchなどを使ってもEXE_BAD_ACCESSなどのアクセス共有違反をキャッチ出来ないケースがある(シミュレータではできず、実機ではできることも多い。デバッグができない)
アプリが唐突に落ちてしまい、次回起動したとき最初から操作してもらうのは、いかがなものかと考えておられる人も多いのでは?
そこで、シグナルをキャッチする処理をかましてやることにした。
〜AppDelegate.mにて
#include <signal.h> void Clientsigcatch(int sig) { /* ここで終了に必要な処理 (次回起動時に現状を復元するため、変数をファイルに書き込む等) */ signal(sig,SIG_DFL); } //シグナルをキャッチする設定 bool signalSetting(){ struct sigaction myAction; memset( &myAction, 0, sizeof(struct sigaction) ); myAction.sa_handler = Clientsigcatch; if (sigfillset(&myAction.sa_mask) < 0){ printf("sigfillsetエラー"); return false; } myAction.sa_flags = SA_RESTART; signal(SIGILL ,Clientsigcatch); signal(SIGSEGV,Clientsigcatch); signal(SIGABRT,Clientsigcatch); signal(SIGALRM,Clientsigcatch); signal(SIGBUS ,Clientsigcatch); signal(SIGCHLD,Clientsigcatch); signal(SIGCONT,Clientsigcatch); signal(SIGFPE ,Clientsigcatch); signal(SIGHUP ,Clientsigcatch); signal(SIGINT ,Clientsigcatch); signal(SIGPIPE,Clientsigcatch); signal(SIGQUIT,Clientsigcatch); signal(SIGTERM,Clientsigcatch); signal(SIGTSTP,Clientsigcatch); signal(SIGTTIN,Clientsigcatch); signal(SIGTTOU,Clientsigcatch); signal(SIGPROF,Clientsigcatch); signal(SIGSYS ,Clientsigcatch); signal(SIGTRAP,Clientsigcatch); signal(SIGXCPU,Clientsigcatch); signal(SIGXFSZ,Clientsigcatch); return true; } //アプリケーション起動直後 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { signalSetting(); //必要 ・・・
シグナルは全部キャッチしてやることにしたけれども、もっといい方法あるかもしれない。
どうしてアプリが落ちてしまったのか?を判断するのはClientsigcatch関数の引数sigで分かる。
たとえば、sig==11はよく出る。
何が原因かは/usr/include/sys/signal.hを参照すると、
#define SIGHUP 1 /* hangup */ #define SIGINT 2 /* interrupt */ #define SIGQUIT 3 /* quit */ #define SIGILL 4 /* illegal instruction (not reset when caught) */ #define SIGTRAP 5 /* trace trap (not reset when caught) */ #define SIGABRT 6 /* abort() */ #if (defined(_POSIX_C_SOURCE) && !defined(_DARWIN_C_SOURCE)) #define SIGPOLL 7 /* pollable event ([XSR] generated, not supported) */ #else /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ #define SIGIOT SIGABRT /* compatibility */ #define SIGEMT 7 /* EMT instruction */ #endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ #define SIGFPE 8 /* floating point exception */ #define SIGKILL 9 /* kill (cannot be caught or ignored) */ #define SIGBUS 10 /* bus error */ #define SIGSEGV 11 /* segmentation violation */ //キミキミ!ここだここだ! #define SIGSYS 12 /* bad argument to system call */ #define SIGPIPE 13 /* write on a pipe with no one to read it */ #define SIGALRM 14 /* alarm clock */ #define SIGTERM 15 /* software termination signal from kill */ #define SIGURG 16 /* urgent condition on IO channel */ #define SIGSTOP 17 /* sendable stop signal not from tty */ #define SIGTSTP 18 /* stop signal from tty */ #define SIGCONT 19 /* continue a stopped process */ #define SIGCHLD 20 /* to parent on child stop or exit */ #define SIGTTIN 21 /* to readers pgrp upon background tty read */ #define SIGTTOU 22 /* like TTIN for output if (tp->t_local<OSTOP) */ #if (!defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)) #define SIGIO 23 /* input/output possible signal */ #endif #define SIGXCPU 24 /* exceeded CPU time limit */ #define SIGXFSZ 25 /* exceeded file size limit */ #define SIGVTALRM 26 /* virtual time alarm */ #define SIGPROF 27 /* profiling time alarm */ #if (!defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)) #define SIGWINCH 28 /* window size changes */ #define SIGINFO 29 /* information request */ #endif #define SIGUSR1 30 /* user defined signal 1 */ #define SIGUSR2 31 /* user defined signal 2 */
#define SIGSEGV 11 /* segmentation violation */
セグメンテーション違反、つまりアクセスできない領域を参照している。
これEXE_BAD_ACCESSということ。
ちなみに、デバッグ時にタスクの赤丸を押してアプリを終了しても、上記関数は呼び出されない(SIGKILLを受信するがLinuxの仕様上キャッチできない)