『新时代 C/C++ 面试题』 GDB 光追

01 Aug 2024 1613 words 6 minutes BY-SA 4.0
develop gdb computer graphics

前情提要:

output

本文代码开源于 gdb-ray-tracing

解释

gdb 内置了一门图灵完备的脚本语言,称为 GDB 或 gdb script 。此语言的初衷是让用户在用 gdb 调试代码时更加灵活,例如:

test.c:

#if 0
bin="$(basename "$0")" && bin="${bin%%.*}" && cc -g "$0" -o"$bin" && exec cgdb ./"$bin" -- --args "$@"
#endif
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
  for (int i = 0; i < 5; i++)
    printf("i = %d\n", i);
  return EXIT_SUCCESS;
}

安装 cgdb 。然后:

chmod +x test.c
./test.c

进入调试界面,在 gdb REPL 中输入:

define hook-stop
  set $str = "currently, i is %d\n"
  if i > 3
    printf $str, i
  end
end
start

接下来不停 next 单步运行,在 最后一次 for 循环中将会在输出 i = 4\n 之前先打印 currently, i is 4\n

解决方案

gdb script 提供了 if, while 等程序控制指令和 printf, print 等输出指令。相比较 cmake 光追,方便之处在于:

不便之处在于:

笔者的解决方案:

复现 bug 方法如下:

Vec3(test_vec f1 fN1 f1)
Vec3_Normalize(result_vec test_vec)
Vec3_Print(result_vec)

结果是 0.577865, -1.577866, 0.577865, 但正确答案是 0.577865, -0.577865, 0.577865

设置

虽然 gdb 是 C 的调试器但 $ 开头的寄存器变量并没有地址,所以用不了卡马克平方根倒数快速算法,只是普通的牛顿迭代法。

用法

封装了一个库 ray-tracing.gdb 。在注释里写了入参和出参的类型和描述。参考 main.gdb ,使用时 source 这个库即可。

接口

python

gdb 有一个可选的 python 接口:

source test.py

test.py:

import gdb

gdb.source(
    """define hook-stop
  set $str = "currently, i is %d\n"
  if i > 3
    printf $str, i
  end
end
start"""
)

所以亦可以在 python 中完成光追的运算再只让 gdb 输出。本文的解决方案并不依赖这个接口。

非常有名的 gdb-dashboard 利用了此接口,为 gdb 实现了一个漂亮的 UI 。

gdb-dashboard

shell

gdb 有一个 shell 接口。用户可以运行 bash, zsh, windows command shell 指令。类似

总结

性能极其极其低下。本文仅仅是对邱奇——图灵论题的一次验证性实验,请勿在任何生产环境中使用它!

初稿撰写于机场候机大厅及万米高空之上。

https://user-images.githubusercontent.com/32936898/199681341-1c5cfa61-4411-4b67-b268-7cd87c5867bb.png https://user-images.githubusercontent.com/32936898/199681363-1094a0be-85ca-49cf-a410-19b3d7965120.png https://user-images.githubusercontent.com/32936898/199681368-c34c2be7-e0d8-43ea-8c2c-d3e865da6aeb.png