Почему gdb оценивает sqrt (3) на 0?
Квадратный корень из 3, по оценкам Wolfram Alpha:
1.7320508075688772935274463415058723669428052538103806280558...
Когда я делаю sqrt(3)
в C, он вычисляет 0. Почему?
EDIT4: вот как вы можете воспроизвести эту проблему в GDB. Создайте test.c
следующим образом:
#include <stdio.h>
#include <math.h>
int main()
{
printf("sqrt(3): %f\n", sqrt(3));
return 0;
}
Compile:
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)
.
Ответы
Ответ 1
Проблема заключается не в отсутствующем объявлении функции (который отсутствует, так как вы включили <math.h>
).
Проблема заключается в отсутствии информации об отладке для sqrt
, которую вы фактически используете. Без этой информации об отладке GDB не знает, какой тип параметра должен перейти к sqrt()
, и что он возвращает.
Вы можете получить требуемую информацию об отладке во многих дистрибутивах Linux, установив пакет libc-debuginfo. Вот что я вижу в такой системе:
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>
Примечание: __sqrt
имеет тот же адрес, что и sqrt
, но GDB знает его тип!
(gdb) p __sqrt(3)
$5 = 1.7320508075688772
(gdb) p __sqrt(3.0)
$6 = 1.7320508075688772
Можно обоснованно утверждать, что это ошибка в GDB. Не стесняйтесь создавать его в GDB bugzilla.
Ответ 2
Я предсказываю, что вы не сделали #include <math.h>
Без объявления функции C по умолчанию возвращается значение функции int
. Число с плавающей запятой может возвращаться как 0 в зависимости от размера вашего int. C также не знает, как преобразовать аргумент функции. Он по умолчанию передаст аргумент как любой тип, которым он является. Если вы передадите целое число в sqrt()
, он не будет преобразован в double, но функция sqrt()
будет интерпретировать битовый шаблон как double
.
Ответ 3
#include <stdio.h>
#include <math.h>
int main()
{
printf("sqrt(3): %f\n", sqrt(3));
return 0;
}
Вывод:
[email protected]:~/scratch$ ./a.out
sqrt(3): 1.732051
Ответ 4
Может быть, вызов sqrt не поддерживается! Может быть, потому что это функция libc. Я не знаю глубинную причину, но следующий тест показывает интересное поведение:
double mysqrt(double x) { return sqrt(x) };
Затем в сеансе gdb:
(gdb) p mysqrt(3)
$1 = 1.7320508075688772
(gdb) p sqrt(3)
$2 = -1209775368
Ответ 5
Чтобы вызвать функцию без информации об отладке, вы должны явно указать gdb тип возвращаемого значения и аргументы, используя функцию-указатель функции. Итак, для вашего примера:
(gdb) print ((double (*) (double)) sqrt) (3)
$1 = 1.7320508075688772