Oracle® Solaris Studio 12.4:dbxtool 教程

退出打印视图

更新时间: 2014 年 10 月
 
 

使用监视和步进

既然您在 Interp::dispatch() 处设置了单个断点,那么如果您再次单击 "Restart"(重新启动)image: 并在 "Debugger Console"(调试器控制台)窗口中按回车键,程序会在 dispatch() 函数包含可执行代码的第一行停止。

image:执行在第 122 行停止的编辑器窗口

    由于您已经确定了传递给 find()argv[0] 问题,因此可以对 argv 使用监视:

  1. 在编辑器窗口中选择 argv 的一个实例。

  2. 右键单击并选择 "New Watch"(新建监视)。"New Watch"(新建监视)对话框将打开,并随选定的文本进行填充:

    image:“New Watch“(新建监视)对话框
  3. 单击 "OK"(确定)。

  4. 要打开 "Watches"(监视)窗口,请选择 "Window"(窗口)> "Watches"(监视)(Alt + Shift + 2 组合键)。

  5. 在 "Watches"(监视)窗口中,展开 argv

    image:argv 已展开的 “Watches“(监视)窗口

    请注意,argv 没有初始化,而且由于 argv 是局部变量,因此可能会从先前的调用中“继承”堆栈上留下的随机值。这会不会是问题的原因?

  6. 单击 "Step Over"(步过)(F8) image: 两次,直到绿色的 PC 箭头指向 int argc = 0;

  7. 由于 argc 将成为 argv 的索引,因此也为 argc 创建监视。请注意,argc 当前也未初始化,并且可能包含不需要的值。

    由于您在 argv 的监视之后为 argc 创建了监视,因此它会在 "Watches"(监视)窗口中显示在第二的位置。

  8. 要按照字母顺序对监视名称进行排序,请单击 "Name"(名称)列标题对该列进行排序。请注意下图中的排序三角形:

    image:包含已排序的监视的 “Watches“(监视)窗口
  9. 单击 "Step Over"(步过)(F8) image:

    argc 现在显示其初始化值 0 并以粗体显示,以表示该值刚刚更改过。

    image:argc 值以粗体显示的 “Watches“(监视)窗口

    应用程序将调用 strtok()

  10. 单击 "Step Over"(步过)步过该函数,并观察 token 是否为 NULL(例如,通过使用气球表达式求值)。

    strtok() 函数有助于拆分字符串,例如拆分为由 DELIMITERS 之一分隔的标记。有关更多信息,请参见 strtok(3) 手册页。

  11. 再次单击 "Step Over"(步过)将标记分配给 argv。循环中将存在对 strtok() 的调用。

    在步过时,您不会进入循环(不再有标记),系统会分配一个 NULL。

  12. 也步过该分配,以达到调用的阈值,从而查明样例程序发生崩溃的位置。

  13. 为了仔细检查程序是否在此处崩溃,步过对 find() 的调用。

    "Signal Caught"(捕获的信号)警报框再次显示。

    image:“Signal Caught“(捕获的信号)警报框
  14. 像以前一样单击 "Discard and Pause"(放弃并暂停)。

    Interp::dispatch() 中停止之后第一次对 find() 的调用实际上就是出错的位置。

    您可以快速返回到初始调用 find() 的位置。

    1. 单击 "Make Caller Current"(使调用方成为当前调用方)image:

    2. find() 的调用点处开启/关闭行断点。

    3. 打开 "Breakpoints"(断点)窗口并禁用 Interp::dispatch() 函数断点。

      dbxtool 的外观应如下所示:

      image:显示两个断点中的一个断点已禁用的编辑器窗口
    4. 向下的箭头表示在第 141 行上设置了两个断点,其中一个断点已禁用。

  15. 单击 "Restart"(重新启动)image: 并在 "Debugger Console"(调试器控制台)窗口中按回车键。

    程序在对 find() 的调用前返回。请注意,按 "Restart"(重新启动)按钮会导致重新启动。进行调试时,重新启动的频率要比刚开始时大很多。


    提示  -  如果您重新生成程序(例如,在搜索和修复错误之后),不需要退出 dbxtool 并重新启动。单击 "Restart"(重新启动)按钮时,dbx 会检测到程序(或其任何成员)已重新编译,因此会将其重新加载。 因此,请考虑将 dbxtool 放在桌面上(可以最小化),以便随时用于调试问题。
  16. 错误在何处?请再次查看监视:

    image:“Watches“(监视)窗口

    请注意,argv[0] 为 NULL,因为对 strtok() 的第一次调用返回 NULL(由于该行为空,没有标记)。

    如果您愿意,可以先修复此错误,然后再继续本教程的剩余部分。

    如果您要在调试器下运行该程序,则可以在调试器中修补代码(如使用断点脚本修补代码中所述)。

该示例代码的开发者很可能已测试此条件并绕过 Interp::dispatch() 的剩余部分。