为什么gdb将sqrt(3)评估为0?

由Wolfram Alpha估算的3的平方根:

1.7320508075688772935274463415058723669428052538103806280558... 

当我在C中执行sqrt(3)时,它的计算结果为0.为什么?

编辑4 :这是你如何在GDB中重现这个问题。 创建test.c如下:

 #include  #include  int main() { printf("sqrt(3): %f\n", sqrt(3)); return 0; } 

编译:

 gcc -O0 -g -Wall -pedantic -ansi -lm -o test test.c 

运行调试器:

 gdb test 

在控制台输入:

 (gdb) break test.c:6 Breakpoint 1 at 0x400578: file test.c, line 6. (gdb) r Starting program: /home/pdedecker/Desktop/test Breakpoint 1, main () at test.c:6 6 printf("sqrt(3): %f\n", sqrt(3)); (gdb) print sqrt(3) $1 = 0 (gdb) s sqrt(3): 1.732051 

我的GDB版本是GNU gdb (GDB) SUSE (7.1-3.12)

问题不在于缺少的函数声明(由于你确实包含了 ,因此不会丢失)。

问题是缺少您实际使用的sqrt调试信息。 没有那个调试信息,GDB不知道要传递给sqrt()参数类型,以及它返回的内容。

您可以通过安装libc-debuginfo软件包在许多Linux发行版上获得所需的调试信息。 这是我在这样一个系统上看到的:

 gdb -q ./a.out Reading symbols from /tmp/a.out...done. (gdb) b main Breakpoint 1 at 0x400558: file tc, line 6. (gdb) r Breakpoint 1, main () at tc:6 6 printf("sqrt(3): %f\n", sqrt(3)); (gdb) p sqrt $1 = {} 0x7ffff7b7fb50 <__sqrt> 

注意:“没有调试信息”

 (gdb) p sqrt(3) $2 = 0 (gdb) p sqrt(3.0) $3 = 0 

注意:符合您的行为。 什么sqrt函数有调试信息?

 (gdb) info func sqrt All functions matching regular expression "sqrt": File ../sysdeps/x86_64/fpu/e_sqrt.c: double __ieee754_sqrt(double); File s_csqrt.c: complex double __csqrt(complex double); File ../sysdeps/x86_64/fpu/e_sqrtf.c: float __ieee754_sqrtf(float); File w_sqrtf.c: float __sqrtf(float); File s_csqrtf.c: complex float __csqrtf(complex float); File ../sysdeps/i386/fpu/e_sqrtl.c: long double __ieee754_sqrtl(long double); File w_sqrtl.c: long double __sqrtl(long double); File s_csqrtl.c: complex long double __csqrtl(complex long double); File ../sysdeps/ieee754/dbl-64/mpsqrt.c: void __mpsqrt(mp_no *, mp_no *, int); File w_sqrt.c: double __sqrt(double); (gdb) p __sqrt $4 = {double (double)} 0x7ffff7b7fb50 <__sqrt> 

注意: __sqrt sqrtsqrt地址相同,但GDB知道它的类型!

 (gdb) p __sqrt(3) $5 = 1.7320508075688772 (gdb) p __sqrt(3.0) $6 = 1.7320508075688772 

可以合理地说这是GDB中的一个错误。 随意在GDB bugzilla中创建一个。

我预测你没有做#include

如果没有函数声明,C将默认函数的返回值为int 。 浮点数可能会返回0,具体取决于int的大小。 C也不知道如何转换函数参数。 它将默认将参数传递为它碰巧的类型。 如果将整数传递给sqrt() ,则不会将其转换为double,但sqrt()函数会将位模式解释为double

要调用没有调试信息的函数,必须使用函数指针强制显式告诉gdb返回和参数的类型。 所以,举个例子:

 (gdb) print ((double (*) (double)) sqrt) (3) $1 = 1.7320508075688772 
 #include  #include  int main() { printf("sqrt(3): %f\n", sqrt(3)); return 0; } 

输出:

 josh@josh-ubuntu:~/scratch$ ./a.out sqrt(3): 1.732051 

也许不支持调用sqrt! 也许是因为它是一个libc函数。 我不知道其深层原因,但以下测试显示了一个有趣的行为:

 double mysqrt(double x) { return sqrt(x) }; 

然后在gdb会话中:

 (gdb) p mysqrt(3) $1 = 1.7320508075688772 (gdb) p sqrt(3) $2 = -1209775368