Why does gdb evaluate sqrt(3) to 0?
Asked Answered
T

5

17

The square root of 3, as estimated by Wolfram Alpha:

1.7320508075688772935274463415058723669428052538103806280558...

When I do sqrt(3) in C, it evaluates to 0. Why?

EDIT4: here's how you can reproduce this issue in GDB. Create test.c as follows:

#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

Run debugger:

gdb test

Enter this at console:

(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

My GDB version is GNU gdb (GDB) SUSE (7.1-3.12).

Tatyanatau answered 25/2, 2011 at 20:59 Comment(14)
Show us the code you're using to get this result.Stringy
Are you including <math.h>?Anna
+1 Jeremiah, I remember the old ages I faced that error too :)Tribade
@Tatyanatau - please post a functional program that shows your problem, including your #include statements, variable declarations, how you're assigning results...Stringy
Yes, I did include math.h and I added the appropriate -lrt flag.Tatyanatau
@Pieter: Does sqrt(3.0) work? And which debugger are you using? Try a printf in your own code.Anna
Obviously, Wolfram Alpha is wrong. *shrug*Trilobite
I meant -lm, of course. My bad. I have been toying with semaphores a lot lately.Tatyanatau
Maybe your debugger isn't evaluating the expression properly.Litton
I tried reproducing my problem in a simple C program, but no luck so far. Trying printf in my program.Tatyanatau
There's no sqrt prototype that accepts integers. Could that be part of the problem?Tatyanatau
@Pieter: The compiler/debugger are supposed to insert a cast to double automatically; maybe the debugger is failing to do that.Anna
I recommend that you include what debugger you are using and also edit the title of your question and your tags because your problem really has nothing to do with C at all.Aluminate
I'm using Eclipse. I added a screenshot to the question.Tatyanatau
M
17

The problem is not the missing function declaration (which isn't missing, since you did include <math.h>).

The problem is missing debug info for the sqrt you are actually using. Without that debug info, GDB has no clue what parameter type to pass to sqrt(), and what it returns.

You can get the required debug info on many Linux distributions by installing libc-debuginfo package. Here is what I see on such a system:

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>

Note: "no debug info"

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

Note: matches your behavior. What sqrt functions do have debug info?

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

Note: __sqrt is at the same address as sqrt, but GDB knows its type!

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

One can reasonably argue this is a bug in GDB. Feel free to create one in GDB bugzilla.

Musicianship answered 27/2, 2011 at 23:58 Comment(1)
Interesting. I went ahead and installed glibc-debuginfo (hope that's what you meant because I couldn't find libc-debuginfo) and I also see that function prototype for __sqrt. print __sqrt(3) does return a valid result. I'd report this bug to the GDB devs, except that I have little experience reporting bugs and I don't know enough about the inner workings of GDB to provide useful information to the developers. Anyway, thanks... I'm marking your answer as accepted!Tatyanatau
A
6

I predict that you didn't do #include <math.h>

Without a function declaration, C will default the return value of a function to int. A floating point number might come back as 0 depending on the size of your int. C will also not know how to convert the function argument. It will default to passing the argument as whatever type it happens to be. If you pass an integer to sqrt() it will not be converted to a double, but the sqrt() function will interpret the bit pattern as double.

Aluminate answered 25/2, 2011 at 21:3 Comment(2)
+1, not only that the return value goes wild. Also the argument is not converted to double if there is no prototype. So sqrt would see some weird bit pattern that it interprets as double and then returns a double in a register or and the caller takes the value in some other (integer) register.Suzannsuzanna
I did include math.h and I did link with -lm.Tatyanatau
A
1

To call a function without debug info, you must explicitly tell gdb the type for the return and arguments, using a function pointer cast. So, for your example:

(gdb) print ((double (*) (double)) sqrt) (3)
$1 = 1.7320508075688772
Athenaathenaeum answered 3/5, 2012 at 15:44 Comment(1)
print (double) sqrt((double)3) returns $6 = 1 I suspect the result is first converted to int and then to double..Kreg
D
0
#include <stdio.h>                                                                                                                                                                      
#include <math.h>

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

  return 0;
}

Output:

josh@josh-ubuntu:~/scratch$ ./a.out 
sqrt(3): 1.732051
Draughts answered 25/2, 2011 at 21:3 Comment(1)
Can you reproduce the problem in GDB? Launch GDB and enter print sqrt(3.0) in the console.Tatyanatau
S
0

Maybe calling sqrt is not supported ! Maybe because it's a libc function. I don't know the deep reason why, but the following test shows an interesting behaviour:

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

Then in a gdb session:

(gdb) p mysqrt(3)
$1 = 1.7320508075688772
(gdb) p sqrt(3)
$2 = -1209775368
Scholarship answered 27/2, 2011 at 16:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.