如何在GDB中评估函数?

42

我想知道为什么在gdb中evaluate函数不起作用?在我的源代码文件中,当在gdb中调试时,这些示例都是错误的评估。

(gdb) p pow(3,2)

$10 = 1

(gdb) p pow(3,3)

$11 = 1

(gdb) p sqrt(9)

$12 = 0
5个回答

35

在gdb中调用函数的语法为:

call pow(3,2)

类型

help call

在 gdb 提示符处获取更多信息。


谢谢!但是调用仍然没有正确运行。(gdb)调用sqrt(9)$ 14 = 0(gdb)调用pow(3,3)$ 15 = 1 - Tim
2
打印命令也会调用函数。实际上,我认为唯一的区别是在调用 void 函数时调用命令不会混淆输出。 - Isak Savo

32
您需要告诉gdb,在查找返回值时使用浮点寄存器而不是普通寄存器,此外还需要为参数提供正确的类型。

即:

(gdb) p ((double(*)())pow)(2.,2.)

$1 = 4


很奇怪,我得到了一个值为$1 = 2的结果。 - daj
1
你好!我是个白痴,一直在苦苦思索double()到底是什么意思?我原以为它表示一个函数指针,可以“返回双重指针,并接受void参数”。所以我试图将其重新转换为((double)())pow)(2.,2.)——但失败了!为什么呢? - Bebe Carabina
1
@BebeCarabina 我理解你的挫败感:我也想避免这种由类型转换引起的严重头部创伤。我在 如何在GDB中评估函数而不需要痛苦的类型转换? 发布了一个相关问题,看看是否有任何解决方案。 - bgoodr

20
我猜编译器和链接器在那些特定函数上做了一些魔法,很可能是为了提高性能。
如果你一定需要使 pow() 在 gdb 中可用,那么你可以创建自己的包装函数:
double mypow(double a, double b)
{
    return pow(a,b);
}

或许还可以将它包装在一个#ifdef DEBUG之类的语句中,以避免在最终二进制文件中增加冗余代码。

顺便说一下,您会注意到其他库函数也可以被调用(并打印其返回值),例如:

(gdb) print printf("hello world")
$4 = 11

4
正确答案已由匿名者给出。 - mattypiper
@mattypiper,“下面由anon提供”的评论中需要一个链接。我认为你的意图是指向anon的答案 - bgoodr

5
实际上,在我的LINUX实现的gcc中,许多数学函数都被替换为特定于其参数类型的变体,通过math.h和bits/mathcalls.h(从math.h中包含)进行一些花式替换。因此,像pow和exp这样的函数被称为__pow或*__GI___exp(根据参数类型和可能的特定版本,您的结果可能会有所不同)。
要确定链接到我的代码中的确切函数是什么,我在调用该函数的行上放置了一个断点,例如,在我的代码中有一行b=exp(c);。然后我在gdb中运行到那个断点,然后使用“step”命令进入该行的调用。然后,我可以使用“where”命令来识别所调用例程的名称。在我的情况下,那就是*__GI___exp。
可能有更聪明的方法来获取这些信息,但是,仅通过运行预处理器(-E选项)或查看生成的汇编代码(-s)就找不到正确的名称。

2
我知道这已经过时了,但如果有人来找,这里是:对我来说,只需执行 p pow 即可,它会给我返回:$28 = {<text variable, no debug info>} 0x7ffff77ffbd0 <__pow> - falstro

1
NAME
   pow, powf, powl - power functions

SYNOPSIS
   #include <math.h>

   double pow(double x, double y);

在这个位置上,你不应该传递一个整数而不是一个双精度浮点数。

 call pow( 3. , 2. )

另外,仅传递一个参数是不够的,你需要像函数期望的那样传递两个参数。

 wrong: call pow ( 3. )

1
实际上,传递整数是可以正常工作的。不确定是否只是巧合,但使用整数调用mypow(请参见我的答案)会产生正确的结果。当调用pow(2.0,2.0)时,我没有从gdb中获得任何输出,但是当使用任何数字调用mypow()时,我都能获得输出。 - Isak Savo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接