2011-02-25 34 views
15

3 का वर्गमूल, के रूप में Wolfram Alpha द्वारा अनुमानित:जीडीबी sqrt (3) से 0 का मूल्यांकन क्यों करता है?

1.7320508075688772935274463415058723669428052538103806280558... 

जब मैं सी में sqrt(3) करते हैं, यह 0. क्यों करने के लिए मूल्यांकन करता है?

EDIT4: यहां बताया गया है कि आप इस समस्या को जीडीबी में कैसे पुन: पेश कर सकते हैं। 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) है।

+10

हमें यह परिणाम प्राप्त करने के लिए आप जिस कोड का उपयोग कर रहे हैं उसे दिखाएं। – birryree

+6

क्या आप '' शामिल हैं? –

+0

+1 यिर्मयाह, मुझे याद है कि पुरानी उम्र में मुझे उस त्रुटि का सामना करना पड़ा :) –

उत्तर

16

(समस्या लापता समारोह घोषणा नहीं है जो isn: एक gdb सत्र में फिर

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

गुम नहीं है, क्योंकि आपने <math.h> शामिल किया था)।

समस्या sqrt के लिए डीबग जानकारी अनुपलब्ध है जिसका आप वास्तव में उपयोग कर रहे हैं। उस डीबग जानकारी के बिना, जीडीबी के पास कोई संकेत नहीं है कि sqrt() पर कौन सा पैरामीटर प्रकार गुजरता है, और यह क्या लौटाता है।

आप 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> 

नोट: __sqrtsqrt के रूप में एक ही पते पर है, लेकिन GDB अपनी तरह जानता है!

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

कोई तर्कसंगत तर्क दे सकता है कि यह जीडीबी में एक बग है। GDB bugzilla में से एक को बनाने के लिए स्वतंत्र महसूस करें।

+0

दिलचस्प। मैं आगे बढ़ गया और 'glibc-debuginfo' स्थापित किया (उम्मीद है कि इसका मतलब है क्योंकि मुझे libc-debuginfo नहीं मिला) और मैं यह भी देखता हूं कि' __sqrt' के लिए फ़ंक्शन प्रोटोटाइप। 'प्रिंट __sqrt (3)' एक वैध परिणाम देता है। मैं इस बग को जीडीबी देवताओं को रिपोर्ट करता हूं, सिवाय इसके कि मुझे थोड़ा अनुभव रिपोर्टिंग बग है और मुझे डेवलपर्स को उपयोगी जानकारी प्रदान करने के लिए जीडीबी के आंतरिक कार्यों के बारे में पर्याप्त जानकारी नहीं है। वैसे भी, धन्यवाद ... मैं आपके उत्तर को स्वीकार करने के रूप में चिह्नित कर रहा हूं! – Pieter

+0

GDB बग दायर की गई है: http://sourceware.org/bugzilla/show_bug.cgi?id=14757 –

0
#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 
+1

क्या आप जीडीबी में समस्या का पुनरुत्पादन कर सकते हैं? जीडीबी लॉन्च करें और कंसोल में 'प्रिंट sqrt (3.0)' दर्ज करें। – Pieter

7

मैं अनुमान है कि आप #include <math.h>

नहीं किया एक समारोह घोषणा के बिना, सी एक समारोह के रिटर्न मान int लागू हो जाएगी। एक फ्लोटिंग पॉइंट नंबर आपके int के आकार के आधार पर 0 के रूप में वापस आ सकता है। सी को यह भी पता नहीं चलेगा कि फ़ंक्शन तर्क को कैसे परिवर्तित किया जाए। यह तर्क को पारित करने के लिए डिफ़ॉल्ट होगा क्योंकि यह जो भी प्रकार होता है। यदि आप sqrt() पर एक पूर्णांक पास करते हैं तो इसे डबल में परिवर्तित नहीं किया जाएगा, लेकिन sqrt() फ़ंक्शन double के रूप में बिट पैटर्न की व्याख्या करेगा।

+0

+1, न केवल वापसी मूल्य जंगली चला जाता है। यदि कोई प्रोटोटाइप नहीं है तो तर्क भी 'डबल' में परिवर्तित नहीं किया जाता है। तो 'sqrt' कुछ अजीब बिट पैटर्न देखेंगे जो इसे' डबल 'के रूप में व्याख्या करता है और फिर रजिस्टर में डबल देता है या कॉलर किसी अन्य (पूर्णांक) रजिस्टर में मान लेता है। –

+0

में मैंने 'math.h' शामिल किया था और मैंने '-lm' से लिंक किया था। – Pieter

0

शायद कॉलिंग को कॉल करना समर्थित नहीं है! शायद क्योंकि यह एक libc समारोह है। मैं गहरी कारण है कि पता नहीं है, लेकिन निम्न परीक्षण एक दिलचस्प व्यवहार दिखाता है:

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

डीबग जानकारी के बिना फ़ंक्शन को कॉल करने के लिए, आपको फ़ंक्शन पॉइंटर कास्ट का उपयोग करके वापसी और तर्क के लिए जीडीबी को स्पष्ट रूप से बताना होगा। तो, आपके उदाहरण के लिए:

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

प्रिंट (डबल) sqrt ((डबल) 3) रिटर्न $ 6 = 1 मुझे लगता है परिणाम पहले int में परिवर्तित किया जाता है और फिर डबल करने के लिए .. – user1656671

संबंधित मुद्दे