बहुत ही सरल कोड से "अवैध हार्डवेयर निर्देश"


9

एक संदिग्ध दावे की जांच करते हुए , मैंने यह छोटा परीक्षण कार्यक्रम लिखा थाnoway.c

int proveit()
{
    unsigned int n = 0;
    while (1) n++;
    return 0;
}

int main()
{
    proveit();
    return 0;
}

यह परीक्षण, मुझे मिलता है:

$ clang -O noway.c
$ ./a.out
zsh: illegal hardware instruction  ./a.out

वाट।

यदि मैं अनुकूलन के बिना संकलन करता हूं तो यह उम्मीद के मुताबिक लटक जाता है। मैंने असेंबली को देखा, और सभी घंटियाँ और सीटी बजने के बिना mainफ़ंक्शन इस तरह दिखता है:

_main:                                  ## @main
    pushq   %rbp
    movq    %rsp, %rbp
    ud2

जहाँ ud2स्पष्ट रूप से अपरिभाषित व्यवहार के लिए एक निर्देश है। उपर्युक्त संदिग्ध दावा, "एक फ़ंक्शन जो कभी नहीं लौटता है वह यूबी है", प्रबलित है। मुझे अभी भी विश्वास करना मुश्किल है। वास्तव में!? आप सुरक्षित रूप से स्पिन लूप नहीं लिख सकते हैं?

इसलिए मुझे लगता है कि मेरे सवाल हैं:

  1. क्या यह सही रीडिंग है जो चल रहा है?
  2. यदि हां, तो क्या कोई मुझे कुछ आधिकारिक संसाधन की ओर इशारा कर सकता है जो इसे सत्यापित करता है?
  3. ऐसी स्थिति क्या है जिसमें आप इस प्रकार का अनुकूलन चाहते हैं?

प्रासंगिक जानकारी

$ clang --version
Apple clang version 11.0.0 (clang-1100.0.20.17)
Target: x86_64-apple-darwin18.6.0
Thread model: posix
InstalledDir: /Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

3
IIRC, हस्ताक्षरित int अतिप्रवाह UB है।
Wildplasser

1
int n = 0unsigned int n = 0;while (1);
^ ^ ^ ^ ^

1
हम्म ... कंपाइलर एक्सप्लोरर क्लैंग को -O gcc.godbolt.org/z/NTCQYT और इसके बिना लाइन-बाय लाइन ट्रांसलेशन के साथ सेल्फ-टारगेट जम्प इंस्ट्रक्शन मिलता है। कई संस्करणों में सुसंगत लगता है। लेकिन मुझे यह भी याद है (हालांकि यह नहीं दिखेगा) कि सी मानक कहता है कि एक गैर-समाप्ति ub है अगर यह साइड-इफ़ेक्ट फ्री है । यहाँ हैंस बोहम ने यह समझाते हुए कि यह कुछ अन्यथा असंभव-संकलक अनुकूलन की अनुमति देता है: open-std.org/jtc1/sc22/wg14/www/docs/n1528.htm
Gene

1
अपरिभाषित व्यवहार को पूर्णांक अतिप्रवाह पर हस्ताक्षरित किया जाता है, न कि अनंत लूप पर। आप का उपयोग करके इसे ठीक कर सकता हैunsigned int
एम एम

2
@ मुझे नहीं लगता कि यह ऐसा कहता है। गैर-कब्ज नियंत्रण अभिव्यक्तियों के साथ साइड-फ्री-लूप को समाप्त करने के लिए माना जा सकता है ( port70.net/~nsz/c/c11/n1570.html#6.8.5p6 ) लेकिन व्यस्त लूपिंग ठीक होनी चाहिए। यूबी पूर्णांक ओवरफ्लो में है, हालांकि मैं यूडी निर्देश के साथ उदाहरण को पुन: पेश नहीं कर सकता।
पीएसकोकिक

जवाबों:


3

यदि आपको उस कोड के लिए ud2 मिलता है जो अब प्रश्न में है, तो संकलक एक अनुरूप C संकलक नहीं है। आप एक कंपाइलर बग की रिपोर्ट कर सकते हैं।

ध्यान दें कि C ++ में यह कोड वास्तव में UB होगा। जब थ्रेड्स जोड़े गए (क्रमशः C11 और C ++ 11), तो किसी भी थ्रेड के लिए आगे की प्रगति की गारंटी को रखा गया था, जिसमें एक प्रोग्राम का मुख्य निष्पादन थ्रेड शामिल है जो बहु-थ्रेडेड नहीं है।

C ++ में सभी थ्रेड्स को अंततः प्रगति करनी चाहिए, बिना किसी अपवाद के। सी में हालांकि, एक लूप जिसकी नियंत्रित अभिव्यक्ति एक निरंतर अभिव्यक्ति है उसे प्रगति की आवश्यकता नहीं है। मेरी समझ यह है कि सी ने इस अपवाद को जोड़ा क्योंकि यह while(1) {}थ्रेड को लटकाने के लिए एंबेडेड कोडिंग में पहले से ही आम चलन था ।

अधिक विस्तृत उत्तरों के साथ इसी तरह का प्रश्न


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

मानक समिति जो कहना चाहती है, उसके बारे में एक बेहतर वाक्यांश यह है कि यदि एक निश्चित ऑपरेशन के दौरान लूप के भीतर सब कुछ डिफाइन करने से प्रोग्राम के व्यवहार पर कोई असर नहीं पड़ेगा, तो लूप के निष्पादन को एक पूरे अतीत के रूप में दर्शाया जाएगा, जो कि ऑपरेशन नहीं माना जाएगा। व्यवहार का अवलोकन परिवर्तन।
सुपरकैट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.