Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何在展开Nil时拦截EXC_BAD_指令_Ios_Swift_Exception Handling_Signals - Fatal编程技术网

Ios 如何在展开Nil时拦截EXC_BAD_指令

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

我正在基于(,我知道PLCRashReporter,,我不能使用它,我需要自己运行一些基本的崩溃日志系统,尽管有限。谢谢)

我的代码为大多数信号注册异常处理程序(使用
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()
设置的,这一事实应该是一个提示

(我在这里说的都是我有限的知识,所以请随意添加答案/评论,并在您认为合适的情况下进行更正)