2008-11-11 14 views
8

मैं एक सी ++ प्रोग्राम लिख रहा हूं जो काम नहीं करता है (मुझे सेगमेंटेशन गलती मिलती है) जब मैं ऑप्टिमाइज़ेशन के साथ संकलित करता हूं (विकल्प-ओ 1, -ओ 2, -ओ 3 , इत्यादि), लेकिन जब मैं अनुकूलन के बिना इसे संकलित करता हूं तो यह ठीक काम करता है।जीसीसी: प्रोग्राम संकलन विकल्प के साथ काम नहीं करता है- ओ 3

क्या कोई मौका है कि त्रुटि मेरे कोड में है? या मुझे लगता है कि यह जीसीसी में एक बग है?

मेरा जीसीसी संस्करण 3.4.6 है।

क्या इस तरह की समस्या के लिए कोई ज्ञात कामकाज है?

मेरे प्रोग्राम के अनुकूलित और अप्रत्याशित संस्करण के बीच गति में एक बड़ा अंतर है, इसलिए मुझे वास्तव में अनुकूलन का उपयोग करने की आवश्यकता है।


यह मेरा मूल मज़ेदार है। एक है कि अनुकूलन का कोई स्तर के साथ ठीक काम करता है और अनुकूलन के किसी भी स्तर के साथ एक विभाजन गलती फेंकता है:

struct distanceToPointSort{ 
    indexedDocument* point ; 
    distanceToPointSort(indexedDocument* p): point(p) {} 
    bool operator() (indexedDocument* p1,indexedDocument* p2){ 
     return distance(point,p1) < distance(point,p2) ; 
    } 
} ; 

और यह एक अनुकूलन के किसी भी स्तर के साथ दोषरहित काम करता है:

struct distanceToPointSort{ 
    indexedDocument* point ; 
    distanceToPointSort(indexedDocument* p): point(p) {} 
    bool operator() (indexedDocument* p1,indexedDocument* p2){ 

     float d1=distance(point,p1) ; 
     float d2=distance(point,p2) ; 

     std::cout << "" ; //without this line, I get a segmentation fault anyways 

     return d1 < d2 ; 
    } 
} ; 

दुर्भाग्य से, यह समस्या पुनरुत्पादन करना मुश्किल है क्योंकि यह कुछ विशिष्ट मानों के साथ होता है। मुझे एक हजार से अधिक वैक्टरों में से केवल एक को क्रमबद्ध करने पर सेगमेंटेशन गलती मिलती है, इसलिए यह वास्तव में प्रत्येक वेक्टर के मूल्यों के विशिष्ट संयोजन पर निर्भर करता है।

+0

यह निश्चित रूप से आपके कोड में एक बग है, जीसीसी में नहीं। एक सभ्य उत्तर प्राप्त करने के लिए कुछ कोड या कुछ और जानकारी पोस्ट करें। आप अपने आवेदन में वास्तव में क्या कर रहे हैं, यह कैसे डिज़ाइन किया गया है, "यह अनुकूलन के साथ काम नहीं करता" से अधिक कुछ है :) एसईजीवी मेमोरी या पॉइंटर समस्या इंगित करता है, इसलिए वहां –

+0

शुरू करें मैं ट्रॉल को कॉल करता हूं। यदि मूल पोस्टर इस प्रश्न को लिखने के लिए प्रोग्रामिंग के बारे में पर्याप्त जानता था, तो मूल पोस्टर को प्रश्न का उत्तर पता था। किसी भी कोड नमूने की अनुपस्थिति पर भी विचार करें। –

+0

कोड के बिना, कोई मौका नहीं है कि हम इस पर आपकी सहायता कर सकते हैं। मुझे डर लग रहा है। –

उत्तर

8

अब आपने कोड खंड लिखा है और एक कामकाजी कामकाज पाया गया है (@ विन्डोज प्रोग्रामर का जवाब), मैं कह सकता हूं कि शायद आप जो खोज रहे हैं वह -ffloat-store है।

-ffloat-स्टोर

रजिस्टरों में चल बिन्दु चर की दुकान मत करो, और अन्य विकल्पों को बदल सकते हैं कि एक चल बिन्दु मूल्य एक रजिस्टर या स्मृति से लिया जाता है कि क्या रोकना।

यह विकल्प 68000 जैसे मशीनों पर अवांछनीय अतिरिक्त परिशुद्धता को रोकता है जहां फ्लोटिंग रजिस्ट्रार (68881 का) डबल की तुलना में अधिक सटीकता रखते हैं। इसी प्रकार x86 आर्किटेक्चर के लिए। अधिकांश कार्यक्रमों के लिए, अतिरिक्त परिशुद्धता केवल अच्छा है, लेकिन कुछ कार्यक्रम आईईईई फ्लोटिंग पॉइंट की सटीक परिभाषा पर भरोसा करते हैं। ऐसे कार्यक्रमों के लिए -फ्लैट-स्टोर का उपयोग करें, उन्हें सभी प्रासंगिक इंटरमीडिएट कंप्यूटेशंस को चर में स्टोर करने के लिए संशोधित करने के बाद।

स्रोत: http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Optimize-Options.html

4

आप एक एलियासिंग समस्या में भाग ले रहे हैं (या यह एक लाख अन्य चीजें हो सकती है)। -फिक्ट-एलाइजिंग विकल्प देखें।

इस प्रकार का प्रश्न बिना किसी जानकारी के ठीक से जवाब देना असंभव है।

+0

-fstrict-aliasing डिफ़ॉल्ट रूप से अक्षम किया गया है –

+0

यह जीसीसी 4.3 –

5

त्रुटि आपके कोड में है। ऐसा लगता है कि आप ऐसा कुछ कर रहे हैं जो सी मानक के अनुसार अपरिभाषित व्यवहार का आह्वान करता है जो कि अनुकूलन के साथ काम करने के लिए होता है, लेकिन जब जीसीसी अपने अनुकूलन करने के लिए कुछ धारणाएं करता है, तब कोड टूट जाता है जब उन मान्यताओं को सत्य नहीं होता है। -Wall विकल्प के साथ संकलित करना सुनिश्चित करें, और -Wextra भी एक अच्छा विचार हो सकता है, और देखें कि क्या आपको कोई चेतावनी मिलती है या नहीं। आप -ansi या -pedantic को भी आजमा सकते हैं, लेकिन इसके परिणामस्वरूप झूठी सकारात्मक परिणाम हो सकते हैं।

+0

बहादुर कॉल ("त्रुटि आपके कोड में है") के लिए -O2 से शुरू हो गया है लेकिन आप शायद सही हैं। इसके अलावा, यदि यह सी मानक के लिए अवैध है, तो इसे संकलित समय पर पकड़ा जाना चाहिए, रन टाइम पर कोर डंप नहीं करना चाहिए। – paxdiablo

+0

"इसके अलावा, यदि यह सी मानक के लिए अवैध है, तो इसे संकलन समय पर पकड़ा जाना चाहिए" - stdin से int int, int द्वारा विभाजित करें, और संकलन समय पर अनुमान लगाएं कि उपयोगकर्ता शून्य टाइप करेगा? नमस्ते? –

+0

0 द्वारा विभाजित मानक तोड़ नहीं है ... –

7

मुझे लगता है कि आपका कोड पहले गलत है।
हालांकि यह कहना मुश्किल है।

क्या आपका कोड 0 चेतावनियों के साथ संकलित करता है?

g++ -Wall -Wextra -pedantic -ansi 
2

यह लगभग (लगभग) कभी नहीं संकलक है।

सबसे पहले, सुनिश्चित करें कि आप चेतावनी मुक्त कर रहे हैं, साथ-साथ।

यदि इससे आपको "यूरेका" पल नहीं दिया गया है, तो अपने निष्पादन योग्य के कम से कम अनुकूलित संस्करण में एक डीबगर संलग्न करें जो क्रैश हो और देखें कि यह क्या कर रहा है और यह कहां जाता है।

5 आपको 10 मिलेगा कि आपने इस बिंदु से समस्या को ठीक कर दिया है।

2

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

0

वाह, मैं जवाब तो quicly उम्मीद नहीं थी, और इतने सारे ...

त्रुटि एसटीडी का उपयोग कर :: एक std :: संकेत के वेक्टर छँटाई प्रकार पर होता है()

मैं प्रदान करते हैं सख्त कमजोर आदेश देने वाले मज़ेदार।

लेकिन मुझे पता है कि जो मैं प्रदान करता हूं वह सही है क्योंकि मैंने इसे बहुत उपयोग किया है और यह ठीक काम करता है।

प्लस, त्रुटि वेक्टर में कुछ अमान्य सूचक नहीं हो सकती है क्योंकि जब मैं वेक्टर सॉर्ट करता हूं तो त्रुटि होती है। अगर मैं पहले std :: sort को लागू किए बिना वेक्टर के माध्यम से पुन: प्रयास करता हूं, तो प्रोग्राम ठीक काम करता है।

मैंने अभी यह पता लगाने के लिए जीडीबी का उपयोग किया है कि क्या हो रहा है। त्रुटि तब होती है जब std :: sort मेरे functor का आह्वान करता है। स्पष्ट रूप से std :: प्रकार मेरे मज़ेदार को एक अमान्य सूचक पास कर रहा है। (बेशक यह केवल अनुकूलित संस्करण के साथ होता है, ऑप्टिमाइज़ेशन के किसी भी स्तर -ओ, -ओ 2, -ओ 3)

+0

क्या आप सबसे छोटा, पूरा, प्रोग्राम प्रदान कर सकते हैं जिसमें यह समस्या है? –

+0

मैं इसे भी देखना चाहता हूं ... –

+0

मैं भी इसे देखना चाहता हूं। यहां कुछ अजीब बात है, क्योंकि std :: sort का कार्यान्वयन -ओ स्तरों से स्वतंत्र होना चाहिए। –

1

मुझे कुछ टिप्पणियां पढ़ने के बाद यहां कुछ डाउनवॉट प्राप्त करने की उम्मीद है, लेकिन कंसोल गेम प्रोग्रामिंग दुनिया में, यह सामान्य ज्ञान है कि उच्च अनुकूलन स्तर कभी-कभी अजीब किनारे के मामलों में गलत कोड उत्पन्न कर सकते हैं। यह बहुत अच्छा हो सकता है कि किनारे के मामलों को कोड में सूक्ष्म परिवर्तनों के साथ ठीक किया जा सकता है।

+0

कोई डाउनवोट नहीं है, लेकिन आपको आर्टेलियस के उत्तर में एक ही टिप्पणी मिल जाएगी - यदि संकलक -ओ 3 पर खराब कोड उत्पन्न करता है, तो बाधाएं अभी भी अच्छी हैं कि आपका कोड अमान्य है, न कि संकलक में एक बग है। लेकिन अमान्य सी/सी ++ कोड लिखना बहुत आसान है। –

+0

हो सकता है, लेकिन यदि गेम डेवलपर्स का एक टन कोड में बग का पता नहीं लगा सका, और कोड 100% ठीक काम करता है, तो शायद यह तकनीकी रूप से एक बग नहीं है, लेकिन मैं वास्तव में एक बग कहूंगा। –

3

यह शायद ही कभी संकलक गलती है, लेकिन कंपाइलर में उनमें कीड़े हैं, और वे अक्सर अलग-अलग अनुकूलन स्तरों पर प्रकट होते हैं (उदाहरण के लिए ऑप्टिमाइज़ेशन पास में कोई बग है)।

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

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

7

यहाँ कुछ कोड लगता है कि काम करने के लिए है जब तक आप -O3 मारा ...

#include <stdio.h> 

int main() 
{ 
    int i = 0, j = 1, k = 2; 
    printf("%d %d %d\n", *(&j-1), *(&j), *(&j+1)); 
    return 0; 
} 
अनुकूलन के बिना

, मैं "2 1 0"; अनुकूलन के साथ मुझे "40 1 22 9 3680" मिलता है। क्यूं कर? क्योंकि मैं और के अनुकूलित हो गया!

लेकिन मैं जम्मू का पता ले रहा था और जे को आवंटित स्मृति क्षेत्र से बाहर जा रहा था। मानक द्वारा इसकी अनुमति नहीं है। यह सबसे अधिक संभावना है कि आपकी समस्या मानक से समान विचलन के कारण होती है।

मुझे लगता है कि valgrind अक्सर इस तरह के सहायक होते हैं।

संपादित करें: कुछ टिप्पणीकर्ता इस धारणा के तहत हैं कि मानक मनमाने ढंग से पॉइंटर अंकगणित की अनुमति देता है। यह नहीं करता है। याद रखें कि कुछ आर्किटेक्चर में मजाकिया एड्रेसिंग स्कीम हैं, संरेखण महत्वपूर्ण हो सकता है, और अगर आप कुछ रजिस्टरों को ओवरफ्लो करते हैं तो आपको समस्याएं मिल सकती हैं!

[ड्राफ़्ट] मानक के शब्दों

बताया/एक सूचक से/एक पूर्णांक घटाकर पर (जोर जोड़ा):

"अगर दोनों सूचक संकार्य और एक ही सरणी वस्तु के तत्वों के परिणाम बिंदु , या सरणी वस्तु के अंतिम तत्व के बाद एक, मूल्यांकन एक अतिप्रवाह प्रस्तुत करेगा नहीं, अन्यथा, व्यवहार अपरिभाषित है "

देखकर रूप & j भी एक सरणी वस्तु को इंगित नहीं करता है। & जे -1 और & जे + 1 शायद ही कभी भाग ओ को इंगित कर सकता है एक ही सरणी वस्तु एफ। तो बस & जे + 1 का मूल्यांकन करना (अकेले इसे संदर्भित करना) अनिश्चित व्यवहार है।

x86 पर हम बहुत भरोसा कर सकते हैं कि एक पॉइंटर में एक जोड़ना काफी सुरक्षित है और हमें अगली मेमोरी लोकेशन पर ले जाता है। उपर्युक्त कोड में, समस्या तब होती है जब हम उस स्मृति के बारे में धारणा करते हैं, जो निश्चित रूप से मानक पास नहीं जाता है।

+4

कृपया इसे संपादित करें "यहां कुछ खराब कोड है जो गलती से -O3 से कम स्तर पर काम करता है"। निश्चित रूप से आपने बाद में इसे स्पष्ट किया, लेकिन आपकी पहली पंक्ति इस चर्चा के पाठकों को गुमराह करती है। –

+3

कोई भी कोड जो -O3 में विफल रहता है वह खराब कोड है जो गलती से नीचे -O3 काम करता है। जब तक यह वास्तव में एक कंपाइलर बग के लिए नीचे नहीं है, बेशक। यह उदाहरण सिर्फ यह विशेष रूप से स्पष्ट है कि कोड खराब है। मुझे लगता है कि बिंदु को चित्रित करने के लिए जानबूझकर है। –

+0

दरअसल, मानक द्वारा इसकी अनुमति है। आप बस एक पॉइंटर बनाते हैं जो जे को इंगित करता है, फिर पॉइंटर में 1 घटाएं/जोड़ें और इसे कम करें। यह पूरी तरह से कानूनी है, * मानक * आपको पसंद करने वाले किसी भी पॉइंटर को पढ़ने का प्रयास करने की अनुमति देता है। – paxdiablo

0

जैसा कि अन्य ने इंगित किया है, शायद सख्त अलियासिंग। इसे ओ 3 में चालू करें और पुनः प्रयास करें। मेरा अनुमान है कि आप अपने मज़ेदार में कुछ पॉइंटर ट्रिक्स कर रहे हैं (इंट तुलना के रूप में तेज़ फ्लोट? ऑब्जेक्ट टाइप कम 2 बिट्स में?) जो टेम्पलेट फ़ंक्शंस को रेखांकित करने में विफल रहता है। चेतावनियां इस मामले को पकड़ने में मदद नहीं करती हैं। "अगर संकलक सभी सख्त एलियासिंग समस्याओं का पता लगा सकता है तो यह उनसे भी बच सकता है" कोड की एक असंबंधित रेखा को बदलना समस्या को प्रकट कर सकता है या पंजीकरण आवंटन को बदल देता है।

0

जैसा कि अद्यतन प्रश्न दिखाएगा;), समस्या std::vector<T*> के साथ मौजूद है। वैक्टरों के साथ एक आम त्रुटि आरक्षित() है जो आकार बदलनी चाहिए() डी। नतीजतन, आप सरणी सीमाओं के बाहर लिख रहे होंगे। एक अनुकूलक उन लिखने को त्याग सकता है।

1

ठीक है ... यह मेरी सबसे अजीब समस्याओं में से एक है।
मुझे नहीं लगता कि मेरे पास यह प्रमाण है कि यह एक जीसीसी बग है, लेकिन ईमानदारी से ... यह वास्तव में एक जैसा दिखता है।

यह मेरा मूल मज़ेदार है। एक है कि अनुकूलन का कोई स्तर के साथ ठीक काम करता है और अनुकूलन के किसी भी स्तर के साथ एक विभाजन गलती फेंकता है:

struct distanceToPointSort{ 
    indexedDocument* point ; 
    distanceToPointSort(indexedDocument* p): point(p) {} 
    bool operator() (indexedDocument* p1,indexedDocument* p2){ 
     return distance(point,p1) < distance(point,p2) ; 
    } 
} ; 

और यह एक अनुकूलन के किसी भी स्तर के साथ दोषरहित काम करता है:

struct distanceToPointSort{ 
    indexedDocument* point ; 
    distanceToPointSort(indexedDocument* p): point(p) {} 
    bool operator() (indexedDocument* p1,indexedDocument* p2){ 

     float d1=distance(point,p1) ; 
     float d2=distance(point,p2) ; 

     std::cout << "" ; //without this line, I get a segmentation fault anyways 

     return d1 < d2 ; 
    } 
} ; 

दुर्भाग्य से, यह समस्या पुनरुत्पादन करना मुश्किल है क्योंकि यह कुछ विशिष्ट मानों के साथ होता है। मुझे एक हजार से अधिक वैक्टरों में से केवल एक को क्रमबद्ध करने पर सेगमेंटेशन गलती मिलती है, इसलिए यह वास्तव में प्रत्येक वेक्टर के मूल्यों के विशिष्ट संयोजन पर निर्भर करता है।

+1

मुझे लगता है कि मुझे समस्या दिखाई दे रही है। अगर मुझे सही ढंग से याद किया जाता है तो आईईईई फ्लोटिंग पॉइंट मानक आवश्यक न्यूनतम से अधिक सटीक परिशुद्धता को बनाए रखने के लिए कार्यान्वयन की अनुमति देता है, और सटीक मात्रा की अतिरिक्त मात्रा स्थिर नहीं होती है। आपका डी 1 और डी 2 कभी-कभी बराबर होता है, कभी-कभी नहीं। –

+0

जो मैंने सोचा था। ऐसा लगता है कि मेरे मज़ेदार असंगत आदेश देने वाले सिमेंटिक्स दे रहे थे, इसलिए std :: प्रकार भ्रमित हो जाता है या कुछ। फिर भी, समस्या केवल अनुकूलन के साथ क्यों होती है? और मेरा दूसरा फ़ैक्टर ठीक क्यों काम करता है? – GetFree

+0

अन्य ने पूछा है, और मैं दोहरा दूंगा, कृपया एक पूरा कार्यक्रम (यथासंभव छोटा) दें जिससे आपको परेशानी हो। यदि आवश्यक हो तो हार्ड कोड इनपुट। – ejgottl

5

एक प्रयोग के रूप में, यह देखने का प्रयास करें कि क्या यह संकलक को लगातार सबकुछ घूमने के लिए मजबूर करेगा।

volatile float d1=distance(point,p1) ; 
volatile float d2=distance(point,p2) ; 
return d1 < d2 ; 
+1

हां। इसने काम कर दिया। अभी तक कोई सेगमेंटेशन गलती नहीं है। – GetFree

+0

क्या बदसूरत समाधान है, लेकिन मुझे खुशी है कि एक समाधान है। –

+0

मैं अभी भी उत्सुक हूं कि एक खाली स्ट्रिंग को आउटपुट क्यों कर रहा हूं (यानी दूरी की गणना और तुलना करने के बीच कुछ कर रहा है) समस्या हल हो गई। – GetFree

0

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

0

सही जवाब इस थ्रेड के सभी टिप्पणियां अंदर कहीं न कहीं छिपा हुआ है। सबसे पहले: यह कंपाइलर में एक बग नहीं है।

समस्या को फ़्लोटिंग पॉइंट परिशुद्धता के साथ करना है। distanceToPointSort एक ऐसा कार्य होना चाहिए जो कभी भी तर्क (ए, बी) और (बी, ए) दोनों के लिए सच नहीं होना चाहिए, लेकिन यह तब भी हो सकता है जब संकलक कुछ डेटा पथों के लिए उच्च परिशुद्धता का उपयोग करने का निर्णय लेता है। समस्या विशेष रूप से संभव है, लेकिनके बिना x86 तक सीमित नहीं है। यदि तुलनित्र इस तरह से व्यवहार करता है, तो sort फ़ंक्शन उलझन में हो सकता है, और सेगमेंटेशन गलती आश्चर्यजनक नहीं है।

मैं -ffloat-store पर सबसे अच्छा समाधान (पहले से ही सीज़रबी द्वारा सुझाया गया) मानता हूं।

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