典型调试模式
class Button : public MyBaseViewClass
{
...
};
....
void MyBaseViewClass::Resized()
{
//<---- here I want to stop in case MyBaseViewClass is really a Button, but not a ScrollBar, Checkbox or something else. I.e. I want a breakpoint condition on a dynamic (most derived) type
}
在strstr(typeid(*this).name(), "Button")上设置断点这样的简单方法不起作用,因为在typeid lldb上控制台告诉:
(lldb) p typeid(*this)
error: you need to include <typeinfo> before using the 'typeid' operator
error: 1 errors parsing expression
在Python中很容易做到这一点。设置断点-假设它是断点1 -然后执行:
(lldb) break command add -s python 1
Enter your Python command(s). Type 'DONE' to end.
def function (frame, bp_loc, internal_dict):
"""frame: the lldb.SBFrame for the location at which you stopped
bp_loc: an lldb.SBBreakpointLocation for the breakpoint location information
internal_dict: an LLDB support object not to be used"""
this_value = frame.FindVariable("this", lldb.eDynamicDontRunTarget)
this_type = this_value.GetType().GetPointeeType().GetName()
if this_type == "YourClassNameHere":
return True
return False
DONE
这里唯一棘手的一点是,当调用FindVariable时,我传递lldb.eDynamicDontRunTarget
,它告诉lldb获取变量的"动态"类型,而不是静态类型。顺便说一句,我也可以使用lldb.eDynamicRunTarget
,但我碰巧知道lldb不需要运行目标来获得c++动态类型。
这种解决问题的方法很好,因为您不必使用RTTI来工作(尽管这样我们只能获得具有某些虚方法的类的类型-因为我们使用虚函数表来完成此魔术)。它也将比需要在debugee中运行代码的方法要快,因为你的表达式必须这样做。
顺便说一句,如果你喜欢这个技巧,你也可以将断点代码放入某个python文件中的python函数中(只需复制上面的def),然后使用:(lldb) command script import my_functions.py
(lldb) breakpoint command add -F my_functions.function
这样你就不用重复输入了