2012-02-29 98 views
6

我正在开发一个最近增长了大量C++基础的iOS应用程序。 C++并不是我的专长,而且我因例外而感到沮丧。我正在寻找的是一种获取堆栈跟踪到(未处理)异常抛出的站点的方法。我会说“未处理”限定符是可选的;我会打破任何异常抛出作为最后的手段,虽然未处理的例外是理想的。我可以获得未处理(目标)C++异常的堆栈跟踪吗?

我目前得到的是无用的。假设我没有任何相应的异常处理程序越往上调用堆栈,我这样做

std::vector<int> my_vector; 
my_vector.at(40) = 2; // Throws std::out_of_range 

应用程序将在main()突破,我会得到一个日志消息说“终止称为抛出异常。”没有帮助。

将通用try/catch块放在callstack的上方也没有帮助,因为callstack在异常处理期间解除了catch块的位置,使得我不知道异常的实际来源。这也适用于提供我自己的terminate_handler。断言更有用,但它们要求我在某种程度上预测错误情况,这是我不能总是这样做的。即使意外的异常超过了我的先发制人的assert()s,我仍然希望调试器能够进入。

我想避免的是不得不将每个可能在try/catch块中引发异常的调用都包装起来,以便将堆栈跟踪发送到错误。在运行时,我真的不想捕捉这些异常。当它们发生时,这意味着程序执行中存在一个致命的缺陷,并且它无法正常继续。我只是想得到通知,所以我可以确定原因并修复问题,以免再次发生。


在Objective C,我可以把一个象征性的断点objc_exception_throw,任何时候我拧的东西了,我会立即中断执行,并用一个漂亮的堆栈跟踪信息呈现,所以我知道在哪里的问题。很有帮助。

我意识到这种行为实际上只是有用的,因为两种语言之间异常处理的哲学差异。 Objective C异常仅用于表示不可恢复的错误。常规错误处理的任务是通过错误返回码完成的。这意味着任何客观的C异常是一个很好的开发人员断点的候选人。

C++似乎对Exceptions有不同的用处。它们用于处理致命错误例行错误(至少在我正在使用的第三方库中)。这意味着我可能并不想在C++中抛出任何异常,但如果我不能仅在未处理的异常中分解,我仍然会发现该功能很有用。

+0

C●汇编程序时

你可能有唯一的问题是++异常并不是真正用于_routine_错误,但它们有时会被滥用。确实,他们不仅仅是因为不可恢复的错误。 – bames53 2012-02-29 22:27:28

回答

5

你可以快速建立在所有C休息++扔条件在Xcode:

  • cmd+6
  • +” 按钮 - >添加例外断点
    • C++ - >std::out_of_range
    • 在投掷

更新

如果你有很多他们的寿过滤掉,你可能会喜欢:

  • 创建符号断点
  • 符号= __cxa_throw(可能因标准库而异)
  • 操作>调试器命令= bt
  • EVAL后自动继续=开

bt命令日志的回溯。按照这种方式配置,它将自动继续。因此,这将只记录每个抛出的异常的回溯 - 当程序由于未处理的异常而终止时,线索将会在最终的日志回溯(通常是最后一次,除非库重新抛出)之间。

+2

啊,在用户界面中。完善。 – 2012-02-29 21:45:25

+0

但我挣扎。看起来你应该能够只指定某些例外来打破。我使用的是ZXing,它在任何地方都会抛出异常(在正常操作期间每帧几次)。我需要忽略这些。然而,当我在某些完全不相关的东西上设置断点时,例如'std :: out_of_range',所有ZXing的std :: exception子类都会触发断点。这是正常的吗? – 2012-02-29 22:15:31

+0

@MattWilding ok。用这个案例的另一个角度更新。 – justin 2012-02-29 23:12:21

1

在应用程序中,我得到许多C++异常进行调试,我将“Catch C++ Exceptions on Throw”关闭,直到我到达应用程序中将抛出异常的位置,然后打开该选项并通常下一个抛出的异常是我正在寻找的。这将会比错误发生的地方深入几层,但堆栈完好无损,因此您可以确定发生了什么。

0

检查PLCrashReporter。我们将它与我们的应用程序(主要依赖C++)一起使用它,并且即使对于C++代码也会生成堆栈跟踪。使用这不是为iOS的原生写的(苹果的编译器使用R7来保存追溯不是根据官方的ARM EBI符号栈帧)

相关问题