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

时间:2011-02-25 20:59:14

标签: c eclipse math gdb

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

1.7320508075688772935274463415058723669428052538103806280558...

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

EDIT4 :以下是您在GDB中重现此问题的方法。按如下方式创建test.c

#include <stdio.h>                                                                                                                                                                      
#include <math.h>

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)

5 个答案:

答案 0 :(得分:17)

问题不在于缺少的函数声明(由于您确实包含<math.h>),因此不会丢失。

问题是缺少您实际使用的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 t.c, line 6.
(gdb) r

Breakpoint 1, main () at t.c:6
6     printf("sqrt(3): %f\n", sqrt(3));
(gdb) p sqrt
$1 = {<text variable, no debug info>} 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>

注意:__sqrtsqrt位于同一地址,但GDB知道其类型!

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

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

答案 1 :(得分:6)

我预测你没有#include <math.h>

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

答案 2 :(得分:1)

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

(gdb) print ((double (*) (double)) sqrt) (3)
$1 = 1.7320508075688772

答案 3 :(得分:0)

#include <stdio.h>                                                                                                                                                                      
#include <math.h>

int main()
{
  printf("sqrt(3): %f\n", sqrt(3));

  return 0;
}

输出:

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

答案 4 :(得分:0)

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

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

然后在gdb会话中:

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