要查找错误,请再次运行示例程序,然后在不输入命令的情况下按回车键。
$ a.out > display var will display 'var' > Segmentation Fault (core dumped) $
启动包含可执行文件和信息转储文件的 dbxtool。
$ dbxtool a.out core
请注意,dbxtool 命令接受的参数与 dbx 命令相同。
dbxtool 显示与以下示例类似的输出。
请注意以下几点:
在 "Debugger Console"(调试器控制台)窗口中,您将看到一条类似于以下示例的消息:
program terminated by signal SEGV (no mapping at fault address) 0xf8cfb790: strcmp+0x0170: ld [%ol], %gl Current function is Interp::find
即使 strcmp() 函数中发生了 SEGV,dbx 也会自动在第一个帧中显示包含调试信息的函数。请注意,"Call Stack"(调用堆栈)窗口中的堆栈跟踪在当前帧的图标四周有一个边框。
请注意,"Call Stack"(调用堆栈)窗口显示参数名称和值。在该示例中,传递给 strcmp() 的第二个参数为 0x0,name 的值为 NULL。
在编辑器窗口中,第 95 行上的淡紫色长条和一个三角形(而不是绿色条和箭头)表示调用 strcmp() 的位置,而不是错误的实际位置:
如果您没有看到参数值,请检查 .dbxrc 文件中的 dbxenv 变量 stack_verbose 是否设置为 on。您还可以在 "Call Stack"(调用堆栈)窗口中设置详细模式,方法是在该窗口中右键单击并选择 "Verbose"(详细)选项。有关 dbxenv 变量和 .dbxrc 的更多信息,请参见Oracle Developer Studio 12.5:使用 dbx 调试程序 中的 第 3 章, 定制 dbx。
向函数传递错误值作为参数时,函数通常会失败。检查传递给 strcmp() 的值:
"Variables"(变量)窗口自动显示所有本地变量。检查 "Variables"(变量)窗口中参数的值。
单击 "Variables"(变量)选项卡。
请注意,name 的值为 NULL。该值很可能是导致 SEGV 的原因,但我们还是来检查一下另一个参数 (*cp)->name() 的值。
在 "Variables"(变量)窗口中,展开 cp 节点,然后展开 (cp*) 节点。此处所涉及的 name 为 "quit",该名称是有效的:
如果展开 *cp 节点后未显示其他变量,请检查 .dbxrc 文件中的 dbx 环境变量 output_inherited_members 是否设置为 on。通过在窗口中右键单击并选中 "Inherited Members"(继承的成员)复选框来添加复选标记,您还可以显示继承的成员。
使用气球表达式求值确认参数的值。单击进入编辑器窗口,然后将光标悬停在传递至 strcmp() 的 name 变量上方。将显示一个提示,其中,name 的值显示为 NULL。
使用气球表达式求值时,您还可以将光标放置到一个表达式的上方,例如 (*cp)->name()。但是,对于包含函数调用的表达式,会禁用气球表达式求值,因为:
您正在调试一个信息转储文件。
因为在编辑器窗口中随意悬停光标,函数调用可能具有副作用。
由于 name 的值不应为 NULL,因此您需要找出是哪部分代码将该错误的值传递至 Interp::find()。要找出:
通过选择 "Debug"(调试)> "Stack"(堆栈)> "Make Caller Current"(使调用方成为当前调用方)或单击工具栏上的 "Make Caller Current"(使调用方成为当前调用方)按钮(Alt - Page Down 组合键) ,上移调用堆栈。
在 "Call Stack"(调用堆栈)窗口中,双击与 Interp::dispatch() 相对应的帧。
现在编辑器窗口中突出显示了相应的代码:
该代码是未知代码,除 argv[0] 的值为 NULL 外不提供任何线索。
通过动态使用断点和单步执行,调试该问题可能会更加容易。