Debugging 避免gdb中的源级“跳转” 用C++编写的用于调试的C++代码,即选项O0GGDB,使用最新的GCC 5.1.0和GDB 7.9,在使用下一个命令时,GDB中的源代码的显示仍然是非常非线性的。例如,此函数调用可能需要使用单个下一步进行: 7757| SDValue NewRoot = TLI->LowerFormalArguments( 7758| DAG.getRoot(), F.getCallingConv(), F.isVarArg(), Ins, dl, DAG, InVals);

Debugging 避免gdb中的源级“跳转” 用C++编写的用于调试的C++代码,即选项O0GGDB,使用最新的GCC 5.1.0和GDB 7.9,在使用下一个命令时,GDB中的源代码的显示仍然是非常非线性的。例如,此函数调用可能需要使用单个下一步进行: 7757| SDValue NewRoot = TLI->LowerFormalArguments( 7758| DAG.getRoot(), F.getCallingConv(), F.isVarArg(), Ins, dl, DAG, InVals);,debugging,gcc,gdb,Debugging,Gcc,Gdb,然而,它需要四个,显示的执行行是第一个7757,然后是7758,然后是7757,然后是7758。如果函数调用被压缩为一行,那么只需要下一行。如果调用被荒谬地夸大,那么需要显示七个nexts作为注释 7757| SDValue 7758| NewRoot 7759| = #1,6 7760| TLI 7761| -> 7762| LowerFormalArguments( #5 7763| DA

然而,它需要四个,显示的执行行是第一个7757,然后是7758,然后是7757,然后是7758。如果函数调用被压缩为一行,那么只需要下一行。如果调用被荒谬地夸大,那么需要显示七个nexts作为注释

       7757|   SDValue
       7758| NewRoot
       7759| =
  #1,6 7760| TLI
       7761| ->
       7762| LowerFormalArguments(
    #5 7763|       DAG.getRoot(),
       7764| F.getCallingConv(),
    #3 7765| F.isVarArg(),
       7766| Ins,
       7767| dl,
       7768| DAG,
       7769| InVals
#2,4,7 7770| );
因此,它与一条不同的线上的每个函数调用都是一个步进点有关,但并不像这样简单。这与递归函数中的断点尤其混淆,我发现自己正在检查调用堆栈,看它是真正的新调用还是虚假的后退步骤

由于将所有LLVM源代码回流以在一行中包含函数调用并不是一个切实可行的选项,因此是否有一些gcc/gdb选项来控制这种行为


编辑:现在使用clang 3.5和lldb 3.5进行检查:使用clang构建时,只会出现三个NEXT。gdb和lldb在任何一种情况下都会看到相同的下一个行为,即4使用gcc,3使用clang

这种来自调试器的行为是一种GIGO情况-也就是说,通常gdb只是执行调试信息告诉它做的任何事情。也就是说,当出现异常行为时,通常是由于编译器做出的决策。这可能是一个bug,可能值得一个bug报告,但如果出于某种原因它打算以这种方式工作,我也不会感到惊讶


您可以通过使用readelf或objdump检查行表来研究这类问题。

从readelf-debug dump中可以明显看出,对于相同的代码块,clang比gcc发出更多X和Y行的高级地址侏儒操作码,但对于这两种编译器,何时会发生这种情况是不可预测的,例如,自动对象的析构函数是否会在作用域的末尾获得单独的前进,但由于在矮人地带漫无目的地四处游荡,调试器显然无法回避这些中间前进,也就是说,似乎没有任何特定于下一个语句命令可以利用的语句终止符。因此,编译器需要更改高级操作码的粒度,我猜gcc和clang目前都没有对此的公开控件