की अव्यवस्था की अनुमति देता है मेरे पास बहुत पुरानी (और विशाल) 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
[अनुरूप बग रिपोर्ट] (https://llvm.org/bugs/show_bug.cgi?id=9251)। यह वादा नहीं कर रहा है: ध्वज को वास्तव में अभी अनदेखा किया गया है (इसे पहले पहचाना नहीं गया था)। – Quentin
'-फनो-डिलीट-नल-पॉइंटर-चेक' को '& * (int *) x' को प्रभावित नहीं किया जाना चाहिए, जिसे अभी भी' NULL' होने की अनुमति है। Http://gcc.godbolt.org/ पर क्लैंग के साथ जांच कर, बस 'बूल बी (शॉर्ट * पी) {वापसी 0 == और * (int *) पी; } ', क्लैंग सही कोड उत्पन्न करता है। कृपया एक न्यूनतम पूर्ण प्रोग्राम पोस्ट करें जहां आपका कंपाइलर गलत कोड उत्पन्न करता है। – hvd
@ एचवीडी मैंने असली उदाहरण पोस्ट किया है। मुझे यकीन नहीं है कि यह समस्या जीसीसी से संबंधित है, मैंने इसे केवल ऐप्पल एलएलवीएम 8.0 –