用GDB进行水晶调试

DP.*_*DP. 5 debugging gdb crystal-lang

我正在尝试学习使用GDB调试用Crystal编写的程序.这是一个示例:

class Demo
  @array = [] of String

  def bar(url)
    ret = url.downcase * 2
    if ret == "alsj"
      return false
    else
      return ret
    end
  end

  def do(foo)
    @array.push(foo)
    html = bar(foo)
    puts "HI" # GDB breakpoint here
    return html
  end
end

a = Demo.new
puts a.do("HI")
Run Code Online (Sandbox Code Playgroud)

我用--debug标志编译了上面的示例并将其加载到GDB中.然后我让它运行并停在标记线(GDB breakpoint here).现在我有三个问题:

  1. 打印字符串值(例如foo): 当我检查字符串变量时,我经常会看到类似的东西$1 = (struct String *) 0x4b9f18.当我说printf "%s", foo,我什么都没有回来.如何显示字符串变量的当前值?
  2. 优化了. 其他时候我只是$1 = <optimized out>在检查变量时看到.这意味着什么?如何在这种情况下看到价值?
  3. 访问对象变量 如何@array在给定的情况下查看值?p array在当前上下文中没有符号,并p @array返回未知的地址空间修饰符. 编辑:我找到了一种方法:使用p self.array
  4. 消失的变量 在给定的情况下(在行中断puts "HI")我根本看不到变量html:p html在当前上下文中不返回符号.为什么这样,我该如何解决?

Fau*_*lar 6

Crystal 调试功能仍在开发中,因此您看不到某些符号或符号数据已由 LLVM 优化。关于优化输出,有时晶体算法优化得太多,甚至在--debug构建时也是如此。举例:

目前 yield 方法是内联和优化的,所以这不是很容易调试。

3.times do |i|
  pp i
end
Run Code Online (Sandbox Code Playgroud)

但是,您可以使用pp关键字来打印name => value

pp i
i => 1
i => 2
i => 3
Run Code Online (Sandbox Code Playgroud)

您也可以使用debugger关键字设置断点并使用{% debug() %}$ crystal tool expand命令检查宏输出。

另一方面,使用 GDB 等工具可以轻松调试复合语句。

i = 0
while i < 3
  debugger
  i += 1 # i variable is listed by GDB
end
Run Code Online (Sandbox Code Playgroud)

最后,您可以尝试我在调试日常任务中发现的一些技巧。

  1. 打印字符串值:尝试@[NoInline]p &foo.c这将使ARGS数据,您将能够打印所有结构字符串值

使用@[NoInline]属性:

@[NoInline]
def do(foo)
  debugger
end
Run Code Online (Sandbox Code Playgroud)

在 GDB 上:

(gdb) p &foo.c
$1 = (UInt8 *) 0x10008e6c4 "HI"
Run Code Online (Sandbox Code Playgroud)
  1. 优化出来:可能是因为 LLVM 优化了一些方法调用。如果您看到<optimized out>使用@[NoInline]并尝试将实例变量分配给本地变量array = @array

  2. 访问对象变量:使用self.var实例变量。

也用于p array.buffer[0]@size打印数组值。

(gdb) p &array.buffer[0].c
$19 = (UInt8 *) 0x10008e7f4 "HI"
Run Code Online (Sandbox Code Playgroud)
  1. 消失的变量:发生这种情况是因为调试信息不​​够完整。

尝试手动添加调试信息转换或转换值:

@[NoInline]
def do(foo)
  html = bar(foo).as(String)
  html = bar(foo).to_s
  debugger
end
Run Code Online (Sandbox Code Playgroud)

由于.asor.to_s方法,现在 html var 在 GDB 上可见

(gdb) p &html.c
$1 = (UInt8 *) 0x1002fcfec "hihi"
Run Code Online (Sandbox Code Playgroud)