在GDB中,在非调试二进制文件中的命名空间或类中调用c++函数的正确方法是什么?



只要符号存在,GDB的call命令通常可以很好地调用函数。但是,如果函数是在一个命名空间或类中,它将突然无法工作,除非它被编译了调试信息。

例如,假设我有这样一个程序:

#include <iostream>
namespace ns {
void test()
{
std::cout << "ns::test" << std::endl;
}
}
struct cl {
static void test()
{
std::cout << "cl::test" << std::endl;
}
};
void func()
{
std::cout << "func" << std::endl;
}
int main()
{
ns::test();
cl::test();
func();
return 0;
}

我将其保存为test.cpp,用g++ test.cpp -o test编译,然后在GDB中启动:

$ gdb test
GNU gdb (GDB) 11.1
[...]
Reading symbols from test...
(No debugging symbols found in test)
(gdb) start

从GDB调用func工作正常:

(gdb) call (void)func()
func

然而,其他的则没有:

(gdb) call (void)ns::test()
No symbol "ns" in current context.
(gdb) call (void)cl::test()
No symbol "cl" in current context.

如果用-ggdb编译,它可以正常工作,但如果源代码不可用,这通常不是一个选项。

值得指出的是,GDB知道这些函数和它们的地址:

(gdb) info functions
...
0x0000000000001169  ns::test()
0x000000000000119b  func()
0x000000000000124e  cl::test()
...
(gdb) info symbol 0x1169
ns::test() in section .text
(gdb) break cl::test()
Breakpoint 1 at 0x1252

如果我按Tab键,这些名字也会自动完成,即使在call命令中,这意味着在这种情况下,它会自动完成一些不工作的东西。

此外,如果我使用它们的原始名称,调用这些函数也可以正常工作:

(gdb) call (void)_ZN2ns4testEv()
ns::test
(gdb) call (void)_ZN2cl4testEv()
cl::test

这是怎么回事?这是GDB中的一个错误,还是有某种我不知道的特殊语法?

您的c++编译器将ns::test放入符号表中。我们所需要做的就是防止GDB的表达式求值器试图查找不存在的符号ns。要做到这一点,将整个函数名放在单引号中。

(gdb) call (void)'ns::test'()
ns::test

最新更新