キャッチできない例外をキャッチする

@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&LTOSTOP) */
#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の仕様上キャッチできない)