¿Por qué gdb evalúa sqrt (3) a 0?

5 minutos de lectura

avatar de usuario
Pedro

La raíz cuadrada de 3, estimada por Wolfram Alpha:

1.7320508075688772935274463415058723669428052538103806280558...

Cuando lo hago sqrt(3) en C, se evalúa a 0. ¿Por qué?

EDITAR4: así es como puede reproducir este problema en GDB. Crear test.c como sigue:

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

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

Compilar:

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

Ejecutar depurador:

gdb test

Ingrese esto en la consola:

(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

Mi versión de GDB es GNU gdb (GDB) SUSE (7.1-3.12).

  • Muéstranos el código que estás usando para obtener este resultado.

    – 逆さま

    25 de febrero de 2011 a las 20:59

  • ¿Estás incluyendo? <math.h>?

    – Jeremías Willcock

    25 de febrero de 2011 a las 21:02

  • Sí, incluí math.h y agregué lo apropiado -lrt bandera.

    – Pedro

    25 de febrero de 2011 a las 21:04

  • Obviamente, Wolfram Alpha está equivocado. *encogimiento de hombros*

    – CorsiKa

    25 de febrero de 2011 a las 21:06

  • Tal vez su depurador no esté evaluando la expresión correctamente.

    – Justin

    25 de febrero de 2011 a las 21:08

El problema no es la declaración de la función que falta (que no falta, ya que incluyó <math.h>).

El problema es que falta información de depuración para el sqrt en realidad estás usando. Sin esa información de depuración, GDB no tiene idea de qué tipo de parámetro pasar sqrt()y lo que devuelve.

Puede obtener la información de depuración requerida en muchas distribuciones de Linux instalando el paquete libc-debuginfo. Esto es lo que veo en dicho sistema:

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>

Nota: “sin información de depuración”

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

Nota: coincide con su comportamiento. Qué sqrt funciones hacer tiene información de depuración?

(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>

Nota: __sqrt está en la misma dirección que sqrt¡pero GDB conoce su tipo!

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

Uno puede argumentar razonablemente que esto es un error en GDB. Siéntete libre de crear uno en GDB bugzilla.

  • Interesante. Seguí adelante e instalé glibc-debuginfo (espero que eso sea lo que quisiste decir porque no pude encontrar libc-debuginfo) y también veo ese prototipo de función para __sqrt. print __sqrt(3) devuelve un resultado válido. Informaría este error a los desarrolladores de GDB, excepto que tengo poca experiencia en informar errores y no sé lo suficiente sobre el funcionamiento interno de GDB para proporcionar información útil a los desarrolladores. De todos modos, gracias… ¡Marco tu respuesta como aceptada!

    – Pedro

    28 de febrero de 2011 a las 8:11


avatar de usuario
zan lince

Predigo que no hiciste #include <math.h>

Sin una declaración de función, C predeterminará el valor de retorno de una función a int. Un número de coma flotante puede volver a ser 0 dependiendo del tamaño de su int. C tampoco sabrá cómo convertir el argumento de la función. De manera predeterminada, pasará el argumento como cualquier tipo que sea. Si pasas un entero a sqrt() no se convertirá en un doble, pero el sqrt() La función interpretará el patrón de bits como double.

  • +1, no solo que el valor devuelto se vuelve loco. Además, el argumento no se convierte en double si no hay prototipo. Entonces sqrt vería un patrón de bits extraño que interpreta como double y luego devuelve un doble en un registro o y la persona que llama toma el valor en algún otro registro (entero).

    – Jens Gusted

    25 de febrero de 2011 a las 21:11

  • yo incluí math.h y me vinculé con -lm.

    – Pedro

    26 de febrero de 2011 a las 20:13

avatar de usuario
Sean De Nigris

Para llamar a una función sin información de depuración, debe decirle explícitamente a gdb el tipo para el retorno y los argumentos, usando un puntero de función. Entonces, para tu ejemplo:

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

  • print (doble) sqrt((doble)3) devuelve $6 = 1 Sospecho que el resultado se convierte primero a int y luego a doble.

    – usuario1656671

    17/10/2016 a las 11:55


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

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

  return 0;
}

Producción:

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

¡Quizás llamar a sqrt no sea compatible! Tal vez porque es una función libc. No sé la razón profunda por la que, pero la siguiente prueba muestra un comportamiento interesante:

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

Luego, en una sesión de gdb:

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

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad