Ios 如何在展开Nil时拦截EXC_BAD_指令
我正在基于(是,我知道PLCRashReporter,否,我不能使用它,我需要自己运行一些基本的崩溃日志系统,尽管有限。谢谢) 我的代码为大多数信号注册异常处理程序(使用Ios 如何在展开Nil时拦截EXC_BAD_指令,ios,swift,exception-handling,signals,Ios,Swift,Exception Handling,Signals,我正在基于(是,我知道PLCRashReporter,否,我不能使用它,我需要自己运行一些基本的崩溃日志系统,尽管有限。谢谢) 我的代码为大多数信号注册异常处理程序(使用NSSetUncaughtExceptionHandler())和信号处理程序: SIGQUIT SIGILL SIGTRAP SIGABRT SIGEMT SIGFPE SIGBUS SIGSEGV SIGSYS SIGPIPE SIGALRM SIGXCPU SIGXFSZ 它似乎可以很好地处理基本的Objective-C
NSSetUncaughtExceptionHandler()
)和信号处理程序:
SIGQUIT
SIGILL
SIGTRAP
SIGABRT
SIGEMT
SIGFPE
SIGBUS
SIGSEGV
SIGSYS
SIGPIPE
SIGALRM
SIGXCPU
SIGXFSZ
它似乎可以很好地处理基本的Objective-C内容,例如“未识别的选择器发送到实例…”,等等
接下来,我使用以下Swift代码进行了尝试:
var empty:String! = nil
let index = empty.startIndex // < KA-BOOM!
var空:字符串!=无
让index=empty.startIndex/
…但是抛出的异常EXC_BAD_指令
没有被捕获(我的处理程序没有被调用),取而代之的是我熟悉的:
致命错误:在展开可选值时意外发现nil
…在Xcode控制台中
我错过了什么?
表示这种运行时错误可以用SIGTRAP
处理;然而,我已经在处理这个信号,它似乎不起作用
附录:似乎没有针对Swift运行时错误(越界、零展开等)的集中式异常处理系统;看见然而,Xcode仍然能够使用
EXC_BAD_指令
崩溃,所以我的问题是:这怎么可能,为什么我的信号处理程序不能处理
附录2:为了安全起见,我尝试为signal.h中定义的所有20+个信号注册我的信号处理程序(不仅仅是上面列出的那些);不过,没有变化
附录3:苹果的官方文件包含以下片段: 跟踪陷阱[EXC_断点//SIGTRAP] 与异常退出类似,此异常旨在给出 附加调试器在特定时间中断进程的机会 执行过程中的关键点。您可以从自己的服务器触发此异常 使用u内置的u trap()函数编写代码。如果没有附加调试器, 进程终止,并生成崩溃报告 较低级别的库(例如libdispatch)将在 遇到致命的错误。有关错误的其他信息可以 可在碰撞的附加诊断信息部分找到 报告,或在设备的控制台中 如果出现意外情况,Swift代码将以此异常类型终止 运行时遇到条件,例如:
- 具有nil值的非可选类型
- 强制类型转换失败
仍然:为什么我不能用我的
SIGTRAP
信号处理器处理这个问题?TL;DR:当未连接调试程序时,信号处理程序工作正常
为了了解发生了什么,我建立了一个小的演示项目,在该项目中,我为
SIGUSR1
(可用的“用户定义”信号之一)注册了一个信号处理程序,然后使用kill()
函数将所述信号发送到我的进程:
kill(0, SIGUSR1);
起初,我无法让Xcode的调试器跳转到我的信号处理程序,相反,它会在调用kill()
时停在第行,并用红色突出显示它,就像我的问题一样
在阅读之后,我突然想到调试器必须非常依赖于信号,以便能够停止/恢复程序执行,例如在断点处
使用其中一个答案中指定的符号断点:
process handle SIGUSR1 -n true -p true -s false
…我可以使用此命令使Xcode不停止:
kill(pid, SIGUSR1);
…并在调试过程中跳转到我的信号处理程序。我甚至可以进入信号处理器,一个接一个地执行它的语句;从其中显示警报视图等
虽然我无法使用SIGTRAP
(甚至SIGABRT
)获得相同的结果,但当我在没有附加调试程序的情况下启动应用程序时(例如,点击主屏幕上的应用程序图标),我的信号处理程序确实会被调用(我的崩溃日志也会被保存到磁盘!)让它抛出一个快速运行时错误,就像我在问题中提到的那样
我猜测为什么我能够截获发送到实例的
未识别的选择器…
似乎是,作为Objective-C异常,它与Unix信号完全不同,与调试器的工作无关(除非您为“Objective-C异常”设置了一个异常断点)
处理程序是使用不相关的函数NSSetUncaughtExceptionHandler()
设置的,这一事实应该是一个提示
(我在这里说的都是我有限的知识,所以请随意添加答案/评论,并在您认为合适的情况下进行更正)