2015-09-07 10 views
10

printf() डीबगिंग स्टेटमेंट्स की एक जोड़ी बताती है कि एक डबल पॉइंटर जो मैं गुजर रहा हूं वह है, जब प्राप्त करने वाले अंत में संदर्भित किया जाता है, तो एक अलग मूल्य के रूप में बाहर आ रहा है - लेकिन केवल माइक्रोसॉफ्ट विजुअल स्टूडियो (संस्करण 9.0) के तहत। चरणों काफी सरल हैं:एक printf() इस डबल को पॉइंटर द्वारा पारित करने की अनुमति क्यों देता है?

double rho=0;  /* distance from the Earth */ 
    /* ... */ 
    for (pass = 0; pass < 2; pass++) { 
     /* ... */ 
     rho = sqrt(rsn*rsn+rp*rp-2*rsn*rp*cpsi*cos(ll)); 
     printf("\nrho from sqrt(): %f\n", rho); 
     /* ... */ 
    } 
    /* ... */ 
    cir_sky (np, lpd, psi, rp, &rho, lam, bet, lsn, rsn, op); 
    /* ... */ 
} 
/* ... */ 
static void 
cir_sky (
/* ... */ 
double *rho,  /* dist from earth: in as geo, back as geo or topo */ 
/* ... */) 
{ 
    /* ... */ 
    printf("\nDEBUG1: *rho=%f\n", *rho); 

पूरे सी फ़ाइल यहाँ है:

https://github.com/brandon-rhodes/pyephem/blob/9cd81a8a7624b447429b6fd8fe9ee0d324991c3f/libastro-3.7.7/circum.c#L366

मैं उम्मीद है कि पहले printf() में प्रदर्शित मान ही होगा कि के रूप में प्रदर्शित किया जाएगा द्वारा दूसरा, एक डबल को पॉइंटर पास करने के बाद से एक अलग मूल्य नहीं होना चाहिए। और जीसीसी के तहत वे वास्तव में हमेशा एक ही मूल्य हैं। विजुअल स्टूडियो 32-बिट संकलन के तहत वे हमेशा एक ही होते हैं। लेकिन जब यह कोड 64-बिट आर्किटेक्चर के तहत विजुअल स्टूडियो के साथ संकलित किया गया है, तो दो डबल मान अलग हैं!

https://ci.appveyor.com/project/brandon-rhodes/pyephem/build/1.0.18/job/4xu7abnl9vx3n770#L573

rho from sqrt(): 0.029624 

DEBUG1: *rho=0.000171 

यह चिंताजनक है। मैंने सोचा: क्या rho के बीच कोड गणना की गई है और जहां पॉइंटर आखिरकार किसी भी तरह से खराब पॉइंटर अंकगणित द्वारा मूल्य को नष्ट कर देता है? तो मैं सही cir_sky() कॉल ऊपर एक आखिरी printf() कहा, देखने के लिए कि मूल्य पहले से ही उस समय तक या क्या यह कॉल खुद के पाठ्यक्रम में बदल दिया जाता है बदल दिया गया है:

printf("\nrho about to be sent: %f\n", rho); 
    cir_sky (np, lpd, psi, rp, &rho, lam, bet, lsn, rsn, op); 

यहाँ में है कि रेखा है पूरी फ़ाइल के संदर्भ:

https://github.com/brandon-rhodes/pyephem/blob/28ba4bee9ec84f58cfffabeda87cc01e972c86f6/libastro-3.7.7/circum.c#L382

और लगता है क्या?

printf() जोड़ना बग तय किया गया - rho पर पॉइंटर को सही मान पर संदर्भित किया जा सकता है!

के रूप में यहां देखा जा सकता:

https://ci.appveyor.com/project/brandon-rhodes/pyephem/build/1.0.19/job/s3nh90sk88cpn2ee#L567

rho from sqrt(): 0.029624 

rho about to be sent: 0.029624 

DEBUG1: *rho=0.029624 

मैं चक्कर में पड़ कर रहा हूँ।

सी मानक का क्या बढ़िया मामला मैं यहां चल रहा हूं? इस फ़ंक्शन के शीर्ष-स्तरीय दायरे में केवल rho मान का उपयोग क्यों करता है, माइक्रोसॉफ्ट कंपाइलर को इसके मूल्य को सही ढंग से संरक्षित करने के लिए मजबूर करता है? क्या समस्या rho दोनों ब्लॉक के अंदर सेट और उपयोग की जाती है, और विजुअल स्टूडियो उस ब्लॉक के बाहर अपने मूल्य को संरक्षित करने के लिए अस्वीकार नहीं करता है क्योंकि सी मानक के क्विर्क की वजह से मैंने कभी आंतरिक रूप से आंतरिक नहीं किया है?

आप उपरोक्त AppVeyor लिंक पर संपूर्ण निर्माण आउटपुट देख सकते हैं। इस सी फ़ाइल के लिए विशेष रूप से संकलन कदम है, के मामले में समस्या हो सकती है कैसे दृश्य स्टूडियो लाया या संकलन विकल्प है, है:

C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\Bin\amd64\cl.exe /c /nologo /Ox /MD /W3 /GS- /DNDEBUG -Ilibastro-3.7.7 -IC:\Python27-x64\include -IC:\Python27-x64\PC /Tclibastro-3.7.7\circum.c /Fobuild\temp.win-amd64-2.7\Release\libastro-3.7.7\circum.obj 
circum.c 
libastro-3.7.7\circum.c(126) : warning C4244: '=' : conversion from 'double' to 'float', possible loss of data 
libastro-3.7.7\circum.c(127) : warning C4244: '=' : conversion from 'double' to 'float', possible loss of data 
libastro-3.7.7\circum.c(139) : warning C4244: '=' : conversion from 'double' to 'float', possible loss of data 
libastro-3.7.7\circum.c(140) : warning C4244: '=' : conversion from 'double' to 'float', possible loss of data 
libastro-3.7.7\circum.c(295) : warning C4244: '=' : conversion from 'double' to 'float', possible loss of data 
libastro-3.7.7\circum.c(296) : warning C4244: '=' : conversion from 'double' to 'float', possible loss of data 
libastro-3.7.7\circum.c(729) : warning C4244: '=' : conversion from 'double' to 'float', possible loss of data 
libastro-3.7.7\circum.c(730) : warning C4244: '=' : conversion from 'double' to 'float', possible loss of data 

उन चेतावनियों में से कोई भी, मैं क्या देख सकते हैं से, कर रहे हैं में शामिल कोड के लिए यह विशेष पहेली - और यदि वे थे, तो वे सभी संकेत देंगे कि एक फ्लोट वैल्यू कम सटीक हो सकता है (दशमलव परिशुद्धता के लगभग 15 अंकों से 7), यह नहीं कि यह पूरी तरह से बदल सकता है।

यहां, दो संकलन-और-परीक्षण रनों के आउटपुट हैं, जिनमें से पहला असफल रहा और दूसरा - printf() की वजह से? - सफल रहा:

https://ci.appveyor.com/project/brandon-rhodes/pyephem/build/1.0.18/job/4xu7abnl9vx3n770

https://ci.appveyor.com/project/brandon-rhodes/pyephem/build/1.0.19/job/s3nh90sk88cpn2ee

दोनों AppVeyor के अनुसार, ठीक उसी वास्तुकला के लिए कर रहे हैं:

Environment: PYTHON=C:\Python27-x64, PYTHON_VERSION=2.7.x, PYTHON_ARCH=64, WINDOWS_SDK_VERSION=v7.0 
+4

आपने इसे 'पायथन' के साथ क्यों टैग किया? – BrenBarn

+0

क्योंकि सी एक्सटेंशन को संकलित करते समय यह हो रहा है, लेकिन चूंकि त्रुटि एक 'printf' के बीच होती है और सी कोड में अन्य जो पाइथन को कॉल नहीं करती है, मैंने टैग हटा दिया है - और मुझे आशा है कि पाइथन लाइब्रेरी की उपस्थिति वास्तव में सचमुच सचमुच समस्या से कोई लेना देना नहीं है! –

+0

क्या आप इलिप्सिस को '/ * ... * /' या कुछ समान के साथ बदल सकते हैं, या बस उन्हें पूरी तरह से हटा सकते हैं? यह कोड को पढ़ने के लिए वास्तव में कठिन बना रहा है। – Qix

उत्तर

0

इस (दोषपूर्ण) अनुकूलन के एक प्रभाव है?

किसी भी अनुकूलन को बंद करें (DEBUG?) और देखें कि क्या आपको वही प्रभाव मिलता है।

बेशक, यदि आपको लगता है कि यह अनुकूलक है तो आप क्रिक हो जाते हैं और केवल इसे मूर्ख बनाने के लिए कुछ कर सकते हैं उदा। एक स्प्रिंटफ जो कुछ भी नहीं करता है।

इसके अलावा, आप printf भी सूचक ("% 16x", (लंबा) & rho मुद्रित कर सकते हैं) ऐसा नहीं है कि मुझे लगता है कि यह गलत है, लेकिन अगर हम समेट खो रहे हैं तो एक स्वच्छता खंड के रूप में। इसके अलावा, यादृच्छिक बिट्स के साथ अधिकतर युगल का परिणाम आम तौर पर ई +/- 317 रेंज में समाप्त होता है, इसलिए 0.000171 परिणाम पूरी तरह से संदेह होने के लिए थोड़ा उचित है।

+0

ये सभी अच्छे सुझाव हैं लेकिन वास्तव में सवाल का जवाब नहीं है। टिप्पणियों के रूप में बेहतर रखा गया। – kaylum

+2

या तो मेरे पास अभी तक 50r नहीं है इसलिए यह सबसे अच्छा है जो मैं कर सकता हूं। –

+0

@brian_carcich पर्याप्त मेला। लेकिन बेहतर काम करना अधिक प्रतिनिधि अंक प्राप्त करना है और जब तक आप ऐसा नहीं करते हैं तब तक टिप्पणी नहीं करते हैं। नियम एक कारण के लिए हैं। गैर-उत्तर उत्तरों पोस्ट करके नियमों के चारों ओर काम करना वास्तव में ऐसा कुछ नहीं होना चाहिए जो किया जाना चाहिए। – kaylum

1

इस कोड पर मेरा त्वरित रूप से कुछ भी गलत नहीं हुआ है जो गलत या समस्याग्रस्त है। लेकिन, जब printf समस्या हल करता है, तो इसका मतलब है कि कुछ गैर-निर्धारणा मौजूद हैं। आइए संभावित कारणों का विश्लेषण करें:

  1. Concurrency - डेटा दौड़: सबसे आम, लेकिन आप कहते हैं कि यह एकल धागा है।
  2. अनन्य स्मृति: rho यहां प्रारंभ किया गया है, लेकिन शायद कहीं और कुछ और नहीं है और यह चीजों को गड़बड़ कर रहा है। मैं यह देखने के लिए कि क्या वे कुछ के साथ आते हैं, मैं वाल्ग्रिंड (लिनक्स पर) और एड्रेससिनिटर और अन्य सैनिटाइजर्स (क्लांग और जीसीसी के लिए जीसीसी पर भी उपलब्ध होना चाहिए) चलाऊंगा।
  3. जंगली पॉइंटर्स और अन्य आउट-ऑफ-बाउंड एक्सेस: कोड में कुछ भी नहीं जो हम यहां देखते हैं, लेकिन यह अन्य कार्यों को कॉल कर रहा है। फिर, वालग्रिंड और sanitizers चलाओ।
  4. यदि पिछले चरण कम हो जाते हैं, तो अगला सबसे संभावित उम्मीदवार एक एमएसवीसी बग है। कुछ जटिल कोड में चीजों को गड़बड़ाने के लिए एमएसवीसी कुख्यात है, और यह कुछ जटिल है। एमएसवीसी को खुश करने के लिए कई बार मैंने कोड को पुन: व्यवस्थित किया है। कभी-कभी ऑप्टिमाइज़ेशन बंद करना मदद करता है, कभी-कभी ऐसा नहीं होता है। विभिन्न कंपाइलर विकल्पों को आजमाने के लिए डितो। कभी-कभी एक अपडेट/पैच होता है जो मदद करता है, कभी-कभी नहीं होता है। एमएसवीसी के अगले संस्करण के लिए Ditto। मैं डीबगर में डिस्सेबलर को देखने का सुझाव दूंगा, लेकिन आप कहते हैं कि आपके पास विंडोज मशीन तक पहुंच नहीं है। यहां सबसे अच्छी शर्त कोड को आजमाने और सरल बनाने के लिए होगी - कार्यों को कम करें, तर्कों की संख्या घटाएं।
  5. अन्य संभावित कारण भी हैं। उदाहरण के लिए, हो सकता है कि स्टैक किसी कारण से गड़बड़ हो जाए - शायद पाइथन रनटाइम के साथ बातचीत करते समय। & को एक पायथन एक्सटेंशन के बजाय इसे "नियमित" सी कोड के रूप में चलाने का प्रयास करें। अन्य कार्यों में कॉल को हटा दें (यदि यह गणनाओं के साथ गड़बड़ हो जाता है, तो कभी भी ध्यान न दें, आप बस समस्या का पता लगाने की कोशिश कर रहे हैं)।

किसी भी मामले में, मैं आपको विंडोज मशीन पर अपने हाथ लेने और इसे डीबग करने की सलाह देता हूं। मेरे अनुभव में, ऐसी समस्याओं के निचले भाग तक पहुंचने का यह सबसे अच्छा तरीका है।

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

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