在 dbx 中,大多数事件管理命令都支持可选的事件过滤器修饰符。最简单的过滤器是指示 dbx 在程序执行到断点或跟踪处理程序处后或出现监视条件后测试条件。
如果相应过滤器条件的求值结果为 true(非 0),则会应用事件命令,且程序在断点处停止执行。如果条件的求值结果为 false (0),dbx 会继续执行程序,就好像从未发生过事件。
要在某一行处或函数中设置包含过滤器的断点,请将可选的 - if condition 修饰符语句添加到 stop 或 trace 命令的末尾。
条件可以是任何有效的表达式(包括函数调用),其返回值是布尔值或输入命令时所用语言表示的整数值。
对于像 in 或 at 这样基于位置的断点,作用域便是断点位置的作用域。否则,条件的作用域是输入时的作用域,而不是事件发生时的作用域。可能必须使用反引号操作符(请参见反引号操作符)来精确指定作用域。
例如,以下这两个过滤器是不一样的:
stop in foo -if a>5 stop cond a>5 |
前者在 foo 处中断并测试条件。后者自动单步执行并测试条件。
可以将函数调用用作断点过滤器。在以下示例中,如果字符串 str 中的值是 abcde,则在函数 foo() 中停止执行:
(dbx) stop in foo -if !strcmp(“abcde”,str) |
变量作用域可以用于设置断点过滤器。在以下示例中,当前作用域在 function foo() 中,而 local 是在 main() 中定义的局部变量:
(dbx) stop access w &main`local -if pr(main`local) -in main |
新用户有时会将设置条件事件命令(监视类型命令)与使用过滤器混淆。从概念上来说,“监视”会创建在执行每行代码前必须检查的前提条件(在监视的作用域内)。但即便是有条件触发的断点命令也可以连接过滤器。
假设有这样一个示例:
(dbx) stop access w &speed -if speed==fast_enough |
此命令指示 dbx 监视变量 speed;如果变量 speed 已写入(“监视”部分),则 -if 过滤器生效。dbx 检查 speed 的新值是否等于 fast_enough。如果不等,程序会继续执行,而“忽略”stop 命令。
在 dbx 语法中,过滤器以命令末尾处的 [-if condition] 形式表示。
stop in function [-if condition] |
如果在多线程程序中设置的断点中使用了包含多个函数调用的过滤器,dbx 将在到达断点时停止所有线程的执行,然后对条件求值。如果满足条件且调用了函数, dbx 便会恢复执行调用期间内的所有线程。
例如,可以在多线程应用程序中许多线程调用 lookup() 之处设置以下断点:
(dbx) stop in lookup -if strcmp(name, “troublesome”) == 0 |
dbx 会在线程 t@1 调用 lookup() 时停止,并对条件求值,然后调用恢复所有线程的 strcmp()。如果在函数调用期间 dbx 在另一个线程中遇到断点,便会发出警告,例如:
event infinite loop causes missed events in the following handlers: ... |
Event reentrancy first event BPT(VID 6m TID 6, PC echo+0x8) second event BPT*VID 10, TID 10, PC echo+0x8) the following handlers will miss events: ... |
在这种情况下,如果可以确定条件表达式中调用的函数不会抓取互斥锁,则可使用 -resumeone 事件规范修饰符强制 dbx 只恢复在其中遇到断点的第一个线程。例如,可设置以下断点:
(dbx) stop in lookup -resumeone -if strcmp(name, “troublesome”) == 0 |
在有些情况下,-resumeone 修饰符并不能防止出现问题。例如,它在下列情况下便无能为力:
由于条件以递归方式调用 lookup(),lookup() 上的第二个断点与第一个断点出现在同一个线程中。
运行条件的线程放弃控制权,将其交给另一个线程。
有关事件修饰符的详细信息,请参见事件规范修饰符。