2016-12-02 17 views
8

की अव्यवस्था की अनुमति देता है मेरे पास बहुत पुरानी (और विशाल) Win32 प्रोजेक्ट है जो निहित पॉइंटर को पॉइंटर को कास्टिंग करके नल पॉइंटर के साथ बड़े पैमाने पर चेक का उपयोग करता है। इस तरह:बल नल पॉइंटर

int* x = NULL; //somewhere 
//... code 
if (NULL == &(*(int*)x) //somewhere else 
    return; 

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

this document for GCC के अनुसार वहाँ एक विकल्प -fno हटाना-शून्य-सूचक-जांच है, लेकिन यह LLVM लिए काम नहीं कर लगता है जब O1, O2 या ओ 3 अनुकूलन सक्षम। तो सवाल यह है कि: मैं इस तरह के विकृतियों को अनुमति देने के लिए एलएलवीएम 8.0 कंपाइलर को कैसे मजबूर कर सकता हूं?

अद्यतन। समस्या की जांच करने के लिए असली कामकाजी उदाहरण।

//somewhere 1 
class carr 
{ 
public: 
    carr(int length) 
    { 
     xarr = new void*[length]; 

     for (int i = 0; i < length; i++) 
      xarr[i] = NULL; 
    } 

    //some other fields and methods 

    void** xarr; 
    int& operator[](int i) 
    { 
     return *(int*)xarr[i]; 
    } 
}; 

//somewhere 2 
carr m(5); 

bool something(int i) 
{ 
    int* el = &m[i]; 
    if (el == NULL) 
     return FALSE; //executes in debug mode (no optimization) 

    //other code 
    return TRUE; //executes in release mode (optimization enabled) 
} 

-O0 और -O1, something keeps the null check में और कोड "काम करता है":

something(int):       # @something(int) 
    pushq %rax 
    movl %edi, %eax 
    movl $m, %edi 
    movl %eax, %esi 
    callq carr::operator[](int) 
    movb $1, %al 
    popq %rcx 
    retq 

लेकिन -O2 पर और इसके बाद के संस्करण, the check is optimized out:

something(int):       # @something(int) 
    movb $1, %al 
    retq 
+5

[अनुरूप बग रिपोर्ट] (https://llvm.org/bugs/show_bug.cgi?id=9251)। यह वादा नहीं कर रहा है: ध्वज को वास्तव में अभी अनदेखा किया गया है (इसे पहले पहचाना नहीं गया था)। – Quentin

+1

'-फनो-डिलीट-नल-पॉइंटर-चेक' को '& * (int *) x' को प्रभावित नहीं किया जाना चाहिए, जिसे अभी भी' NULL' होने की अनुमति है। Http://gcc.godbolt.org/ पर क्लैंग के साथ जांच कर, बस 'बूल बी (शॉर्ट * पी) {वापसी 0 == और * (int *) पी; } ', क्लैंग सही कोड उत्पन्न करता है। कृपया एक न्यूनतम पूर्ण प्रोग्राम पोस्ट करें जहां आपका कंपाइलर गलत कोड उत्पन्न करता है। – hvd

+0

@ एचवीडी मैंने असली उदाहरण पोस्ट किया है। मुझे यकीन नहीं है कि यह समस्या जीसीसी से संबंधित है, मैंने इसे केवल ऐप्पल एलएलवीएम 8.0 –

उत्तर

0

पर एक पाठ आधारित खोज करें शून्य। फिर संकलक मोड में कंपाइलर चलाएं और पेपर पर सभी चेतावनियों को प्रिंट करें (यदि आपके पास अभी भी ऐसी तकनीक है)। अब प्रत्येक शून्य के लिए, क्या यह एक समस्याग्रस्त शून्य या अच्छा है? यदि समस्याग्रस्त है, तो इसका नाम बदलें XNULL।

अब यह संभावना है कि सी ++ चेक 640k इंस्टॉल के साथ एक छोटी प्रणाली पर असफल हो सकते हैं, क्योंकि 640k किसी के लिए पर्याप्त है, लेकिन कई जीबी के साथ आपके आधुनिक सिस्टम पर नहीं है। तो बस एक बार relabelled बाहर उन्हें बाहर पट्टी। अगर ऐसा नहीं है। सी ++ आंखों में एक वैध पते के साथ XNULL को "डमी ऑब्जेक्ट" बनाएं।

(उदाहरण के लिए, ऐसा लगता है कि कोड एक लिस्प दुभाषिया है। लिस्प को एक शून्य सूचक और एक डमी पॉइंटर की आवश्यकता है, दुभाषिया लिखने का कोई और आसान तरीका नहीं है)।

+0

यह समाधान नहीं है –

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