C++ GDB如何评估C++;运行时的表达式

C++ GDB如何评估C++;运行时的表达式,c++,gdb,expression,C++,Gdb,Expression,在调试时,我最近注意到GDB能够在调试程序时计算“复杂”表达式,我想知道它是如何做到这一点的。例如,使用以下代码: int main() { std::vector<int> v = {1, 2, 3}; int k = 0; std::cin >> k; v.push_back(k); return v.at(0); } intmain(){ 向量v={1,2,3}; int k=0; 标准:cin>>k; v、 推回(k);

在调试时,我最近注意到GDB能够在调试程序时计算“复杂”表达式,我想知道它是如何做到这一点的。例如,使用以下代码:

int main() {
    std::vector<int> v = {1, 2, 3};
    int k = 0;
    std::cin >> k;
    v.push_back(k);
    return v.at(0);
}
intmain(){
向量v={1,2,3};
int k=0;
标准:cin>>k;
v、 推回(k);
返回v.at(0);
}
我能够编译程序
g++-g myprogram.cpp
,并在GDB中调试它,这样我就可以键入
print v.at(4)
(在动态输入
k
后打印正确的值)和
print v.at(2)==3
,计算结果为真

我想知道GDB是如何做到这一点的。暗示它是“在内存中编译”的东西,但没有进一步详细说明,所以我想知道它是使用某种JIT来实现这一切还是其他什么?他们是否在我键入并运行代码时以内联方式编译代码?在调试上下文中,它们有一个框架来评估C++吗?本质上,我想在我正在编写的用于在断点处计算表达式的调试器中重现这一点,这就是为什么我很好奇GDB是如何做到这一点的

这样我就可以输入打印v.at(4)

gdb可以调用编译成二进制的函数。这正是这里发生的事情。gdb调用
std::vector
成员函数
at()
并为您打印结果,请参阅


还要注意,这是可能的,因为您在代码中使用了
v.at(0)
。如果删除这部分代码,
v.at()
将不会实例化,并且在生成的二进制文件中不可用,因此gdb无法调用它。

简短回答:它不编译代码

长答案:

  • 调用
    print
    命令,该过程在
    printcmd.c
  • 它调用在
    eval.c
    中定义的
    evaluate\u表达式
    ,该表达式通过读取目标内存并在标准运算符的gdb中计算来计算表达式,否则使用
    手动调用函数
  • infcall.c
    中定义了手动调用功能。调用时,过程会停止目标执行(有时不会,因此可能会使具有此功能的多线程程序崩溃)
  • 将代码注入正在调试的程序
  • 通过读取内存检索结果,必要时取消暂停
  • 为了更好地理解,您可以将重点放在手动调用函数的代码上


    注意:
    compile
    print
    /
    call

    不同,我不清楚您希望得到什么样的答案。GDB能够在调试程序的上下文中分析C和C++表达式,借助于二进制中包含的调试信息,并且可能在可用时使用源代码。但是你已经知道了,在这个场合,细节可能会非常冗长。@JohnBollinger我想我必须“使用源代码”,但我想知道的是他们是如何评估表达式的。他们是否在我键入并运行代码时以内联方式编译代码?在调试上下文中,它们有一个框架来评估C++吗?本质上,我想在我正在编写的用于在断点处计算表达式的调试器中重现这一点,这就是为什么我很好奇GDB是如何做到这一点的。谢谢你的问题似乎更多的是C++的重点。我建议您删除C标记。我已经对GDB的源代码进行了一些调查。希望它能帮助你。所以GDB不编译任何东西,而是运行现有代码的部分来计算表达式?是否有GDB用来做这件事的库,或者它是完全以独立的方式编码的?是的,在您发布的示例中。但它也可以编译和注入代码,请参阅,尽管我没有使用此功能。值得一提的是,GDB还有
    compile code
    命令,可以在运行时编译和注入代码,请参阅,例如: