问题:
我有一种情况,我们在发布过程中播放了媒体,objc_exception_throw()在此期间大约播放了5次,但总是被捕获,并且它是媒体播放器以南的方式对象
我已经厌倦了(a)必须手动连续n次,或者(b)在播放完成之前必须禁用断点。
我尝试了什么:
我想做什么:
我想到的一个解决方案是在断点命中时评估堆栈,并在其中列出特定方法或函数时继续。但我不知道该怎么做。
其他想法也欢迎。
答案 0 :(得分:14)
你是用Python做的。
以下定义了一个忽略列表和一个可以作为命令附加到断点的函数。
该函数获取回溯中的函数名称,并使用忽略列表将这些名称与这些名称相交。如果任何名称匹配,它将继续运行该过程。这有效地跳过调试器中的不需要的堆栈。
(lldb) b objc_exception_throw
Breakpoint 1: where = libobjc.A.dylib`objc_exception_throw, address = 0x00000000000113c5
(lldb) script
Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
>>> ignored_functions = ['recurse_then_throw_and_catch']
def continue_ignored(frame, bp_loc, dict):
global ignored_functions
names = set([frame.GetFunctionName() for frame in frame.GetThread()])
all_ignored = set(ignored_functions)
ignored_here = all_ignored.intersection(names)
if len(ignored_here) > 0:
frame.GetThread().GetProcess().Continue()
quit()
(lldb) br comm add -F continue_ignored 1
(lldb) r
我对以下文件进行了尝试,并成功跳过recurse_then_throw_and_catch
内的第一次抛出,并在throw_for_real
内投掷时进入调试器。
#import <Foundation/Foundation.h>
void
f(int n)
{
if (n <= 0) @throw [NSException exceptionWithName:@"plugh" reason:@"foo" userInfo:nil];
f(n - 1);
}
void
recurse_then_throw_and_catch(void)
{
@try {
f(5);
} @catch (NSException *e) {
NSLog(@"Don't care: %@", e);
}
}
void
throw_for_real(void)
{
f(2);
}
int
main(void)
{
recurse_then_throw_and_catch();
throw_for_real();
}
我想您可以将此功能添加到.lldbinit
,然后根据需要从控制台将其连接到断点。 (我认为你不能在Xcode中设置脚本命令。)
答案 1 :(得分:2)
break command add -s python -o "return any('xyz' in f.name for f in frame.thread)"
如果python breakpoint命令返回False
,lldb将继续运行。所以这就是说:如果堆栈中的any
帧的名称中包含字符串'xyz'
,则返回True
(停止)。否则,如果没有框架具有该名称,则此any
表达式将返回False
(继续)。