दिलचस्प पोस्ट
एसोसिएटिव सरणी से PHP निकालें कुंजी जावास्क्रिप्ट: ऑपरेटर ओवरलोडिंग ओरेकल में बूलियन फील्ड JQuery में हर 5 सेकंड फ़ंक्शन को कॉल करने का सबसे आसान तरीका क्या है? जावास्क्रिप्ट – कैसे पता लगाया गया है कि दस्तावेज़ लोड हो रहा है (IE 7 / Firefox 3) क्या बदलते घटना का प्रचार होता है? व्यक्तिगत वर्ग के नाम पर 'से शुरू होता है' चयनकर्ता का उपयोग करना PHP – स्ट्रिंग में वैरिएबल सम्मिलित या सीधे सम्मिलित करें कैसे जैक्सन Wildfly को कॉन्फ़िगर करें? कैसे खुद को हटाए बिना पाठ फ़ाइल की सामग्री को हटाने के लिए TZInfo :: डेटासॉर्सनोटफ़ाउंड त्रुटि विंडोज़ पर रेल v4.1.0 सर्वर शुरू करने के लिए `WinMain @ 16 'के लिए अपरिभाषित संदर्भ सी # में आरे का आकार (लंबाई) क्यों कक्षा में प्रारंभिक केवल = या {} उपयोग कर सकते हैं? आर में निर्देशिका में सभी फ़ाइलों के माध्यम से लुकिंग, एकाधिक आदेशों को लागू करना

सख्त अलियासिंग नियम क्या है?

सी में सामान्य अपरिभाषित व्यवहार के बारे में पूछते समय, सख्त अलियासिंग नियम को संदर्भित किए जाने वाले आत्माओं से अधिक प्रबुद्ध
उनकी बातचीत किस बारे में हो रही है?

वेब के समाधान से एकत्रित समाधान "सख्त अलियासिंग नियम क्या है?"

एक विशिष्ट स्थिति में आप सख्त अलियासिंग समस्याओं का सामना करते हैं, जब आपके सिस्टम के शब्द आकार के बफ़र पर (जैसे uint16_t या uint16_t लिए एक संकेतक) एक संरचना (जैसे एक डिवाइस / नेटवर्क संदेश) को uint16_t जब आप ऐसे बफर पर एक संरचना को ओवरले करते हैं, या पॉटर का कास्टिंग करके इस तरह के एक स्ट्रिंग पर बफर आप सख्त अलियासिंग नियमों का आसानी से उल्लंघन कर सकते हैं।

तो इस तरह की स्थापना में, अगर मैं किसी संदेश को भेजना चाहता हूं तो मुझे दो असंगत पॉइंटर्स मेमोरी के एक ही हिस्से की ओर इशारा करना होगा। फिर मैं कुछ इस तरह से नीच कोड कर सकता हूँ:

 struct Msg { unsigned int a; unsigned int b; }; void SendWord(uint32_t); int main() { // Get a 32-bit buffer from the system uint32_t* buff = malloc(sizeof(Msg)); // Alias that buffer through message Msg* msg = (Msg*)(buff); // Send a bunch of messages for (int i =0; i < 10; ++i) { msg->a = i; msg->b = i+1; SendWord(buff[0]); SendWord(buff[1]); } } 

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

(जीसीसी को अलियासिंग चेतावनी देने की अपनी क्षमता में कुछ असंगत दिखता है, कभी-कभी हमें मित्रतापूर्ण चेतावनी देते हैं और कभी-कभी नहीं।)

देखने के लिए कि यह व्यवहार अपरिभाषित क्यों है, हमें इस बारे में सोचना होगा कि कड़ी अलियासिंग नियम कम्पाइलर कैसे खरीदता है। असल में, इस नियम के साथ, लूप की हर buff के buff की सामग्री को ताज़ा करने के लिए निर्देशों को सम्मिलित करने के बारे में सोचना नहीं पड़ता है। इसके बजाय, अनुकूलन करते समय, अलियासिंग के बारे में कुछ नाराज़गी अप्रत्याशित मान्यताओं के साथ, यह उन निर्देशों को छोड़ सकता है, लूप buff[0] और buff[1 ] को सीपीयू रजिस्टरों में लूप चलाने से पहले, और लूप के शरीर को गति दे सकता है। सख्त अलियासिंग पेश किए जाने से पहले, संकलक को भ्रम की स्थिति में रहना पड़ता था कि किसी भी समय किसी से कहीं से किसी भी समय buff की सामग्री बदल सकती है तो एक अतिरिक्त प्रदर्शन किनारे पाने के लिए, और मानते हुए कि ज्यादातर लोग टाइप-पेन पॉइंटर्स नहीं करते, सख्त अलियासिंग नियम पेश किया गया था।

ध्यान रखें, यदि आप सोचते हैं कि उदाहरण का अनुक्रमित है, तो ऐसा तब भी हो सकता है जब आप बफर को किसी अन्य फ़ंक्शन को भेज रहे हों, जो आपके लिए भेज रहे हैं, यदि आपके पास है तो

 void SendMessage(uint32_t* buff, size_t size32) { for (int i = 0; i < size32; ++i) { SendWord(buff[i]); } } 

और इस सुविधाजनक समारोह का लाभ उठाने के लिए हमारे पहले लूप को दोबारा लिखे

 for (int i =0; i < 10; ++i) { msg->a = i; msg->b = i+1; SendMessage(buff, 2); } 

कंपाइलर SendMessage इनलाइन करने का प्रयास करने के लिए पर्याप्त या सक्षम नहीं हो सकता या हो सकता है और यह लोड करने के लिए या पुनः लोड करने का फैसला नहीं कर सकता या हो सकता है। अगर SendMessage एक अन्य एपीआई का हिस्सा है जो अलग से संकलित है, तो संभवत: बूंद सामग्री को लोड करने के निर्देश हैं फिर से, हो सकता है कि आप सी ++ में हों और यह कुछ टेम्पलेट हेडर ही कार्यान्वयन है, जिसे कंपाइलर सोचता है कि वह इनलाइन कर सकता है। या हो सकता है यह आपकी कुछ सुविधा है जो आपने अपनी सुविधा के लिए अपनी फाइल में लिखा है। वैसे भी अनिर्धारित व्यवहार अभी भी सामने आ सकता है। यहां तक ​​कि जब हम हुड के नीचे कुछ हो रहा है, तो यह अभी भी नियम का उल्लंघन है, इसलिए कोई अच्छी तरह से परिभाषित व्यवहार की गारंटी नहीं है। तो सिर्फ एक समारोह में लपेटकर, जो हमारे शब्द सीमांकित बफर को जरूरी नहीं है, मदद करते हैं।

तो मैं इस के आसपास कैसे मिलता है?

  • एक संघ का उपयोग करें सशक्त अलियासिंग के बारे में शिकायत किए बिना अधिकांश संकलक इसका समर्थन करते हैं यह C99 में अनुमत है और सी 11 में स्पष्ट रूप से अनुमति है।

     संघ {
         संदेश संदेश;
         अहस्ताक्षरित पूर्णांक asbuffer [sizeof (संदेश) / sizeof (अहस्ताक्षरित int)];
     };
    
  • आप अपने कंपाइलर में सख्त अलियासिंग अक्षम कर सकते हैं ( f [no-] gcc में सख्त-एलियासिंग )

  • आप अपने सिस्टम के शब्द के बदले अलियासिंग के लिए char* उपयोग कर सकते हैं। नियम char* ( signed char और unsigned char सहित) के लिए एक अपवाद की अनुमति देते हैं। यह हमेशा मान लिया जाता है कि char* उपनाम अन्य प्रकार हालांकि यह अन्य तरीके से काम नहीं करेगा: कोई भी धारणा नहीं है कि आपके संरचना ने वर्णों के बफ़र को नामित किया है

शुरुआती सावधान रहना

यह केवल एक संभावित क्षेत्र है, जब एक दूसरे पर दो प्रकार के ओवरलेिंग करना होता है। आपको एंडियननेस , वर्ड संरेखण और पैकिंग स्ट्रैक्टस के माध्यम से संरेखण के मुद्दों से कैसे सही तरीके से व्यवहार करना सीखना चाहिए।

मुझे सबसे अच्छा स्पष्टीकरण मिल गया है माईक एक्टन द्वारा, सख्त अलिज़िंग को समझना यह PS3 विकास पर थोड़ा ध्यान केंद्रित करता है, लेकिन यह मूल रूप से सिर्फ जीसीसी है।

लेख से:

"सख्त एलियासिंग एक धारणा है, जो सी (या सी ++) कंपाइलर द्वारा बनाई गई है, जो अलग-अलग प्रकार के ऑब्जेक्ट्स को डिफरेंसिंग पॉइंटर्स एक ही मेमोरी स्थान (यानी उर्फ ​​प्रत्येक दूसरे।) को संदर्भित नहीं करेगा"

तो मूल रूप से यदि आपके पास कोई int* जिसमें कुछ स्मृति को इंगित किया गया है और फिर आप उस मेमोरी में एक float* को इंगित करते हैं और इसे एक float रूप में प्रयोग करते हैं जिसे आप नियम तोड़ते हैं यदि आपका कोड इसका सम्मान नहीं करता है, तो कंपाइलर के अनुकूलक आपके कोड को तोड़ देगा।

नियम के अपवाद एक char* , जिसे किसी भी प्रकार के बिंदु पर इंगित करने की अनुमति है

यह सख्त अलियासिंग नियम है, जो सी ++ 03 मानक के खंड 3.10 में पाया गया है (अन्य जवाब अच्छी स्पष्टीकरण देते हैं, लेकिन कोई भी नियम स्वयं प्रदान नहीं करता है):

यदि कोई प्रोग्राम किसी ऑब्जेक्ट के संग्रहीत मूल्य को निम्नलिखित प्रकारों में से एक के अलावा अन्य के एक लावल्यू के माध्यम से एक्सेस करने का प्रयास करता है तो व्यवहार अनिर्धारित है:

  • वस्तु का गतिशील प्रकार,
  • ऑब्जेक्ट के डायनामिक प्रकार का एक सीवी-योग्य संस्करण,
  • एक प्रकार जो ऑब्जेक्ट के डायनेमिक प्रकार से संबंधित एक हस्ताक्षरित या अहस्ताक्षरित प्रकार है,
  • एक प्रकार जो हस्ताक्षरित या अहस्ताक्षरित प्रकार वस्तु के गतिशील प्रकार के सीवी-योग्य संस्करण के अनुरूप होता है,
  • कुल मिलाकर या यूनियन का प्रकार जिसमें इसके सदस्यों में से एक के पूर्ववर्ती प्रकार शामिल होते हैं (जिनमें शामिल हैं, पुनरावर्ती, एक सबगैगेट या शामिल यूनियन का सदस्य)
  • ऑब्जेक्ट के डायनामिक प्रकार के एक प्रकार (संभवतः सीवी-योग्य) बेस क्लास प्रकार है,
  • एक char या unsigned char प्रकार

सी +11 11 और सी + 14 शब्दांकन (परिवर्तनों पर बल दिया गया है):

यदि कोई प्रोग्राम किसी ऑब्जेक्ट के संग्रहीत मूल्य को निम्न प्रकारों में से एक के अलावा अन्य के ग्लव्यू के माध्यम से एक्सेस करने का प्रयास करता है तो व्यवहार अनिर्धारित है:

  • वस्तु का गतिशील प्रकार,
  • ऑब्जेक्ट के डायनामिक प्रकार का एक सीवी-योग्य संस्करण,
  • ऑब्जेक्ट के डायनेमिक प्रकार को एक प्रकार समान (जैसा कि 4.4 में परिभाषित किया गया है)
  • एक प्रकार जो ऑब्जेक्ट के डायनेमिक प्रकार से संबंधित हस्ताक्षरित या अहस्ताक्षरित प्रकार है,
  • एक प्रकार जो हस्ताक्षरित या अहस्ताक्षरित प्रकार वस्तु के गतिशील प्रकार के सीवी-योग्य संस्करण के अनुरूप होता है,
  • एक समग्र या यूनियन प्रकार जिसमें इसके तत्वों या गैर-स्थिर डेटा सदस्यों में से एक शामिल होता है (जिसमें एक पुनरावर्ती, एक तत्व या गैर-स्थैतिक डेटा सदस्य का एक सबगैगेट या संघ शामिल है),
  • ऑब्जेक्ट के डायनामिक प्रकार के एक प्रकार (संभवतः सीवी-योग्य) बेस क्लास प्रकार है,
  • एक char या unsigned char प्रकार

दो परिवर्तन छोटा थे: लावलू के बजाय ग्लक्वे्यू , और समग्र / संघ मामले की स्पष्टीकरण

तीसरा परिवर्तन मजबूत गारंटी देता है (मजबूत अलियासिंग नियम को आराम देता है): समान प्रकार की नई अवधारणा जो अब उपनाम के लिए सुरक्षित हैं


सी शब्दिंग (सी -199; आईएसओ / आईईसी 9899: 1 99 6.5 / 7; आईएसओ / आईईसी 9899: 2011 §6.5 ¶7 में सटीक एक ही शब्द का प्रयोग किया जाता है):

किसी ऑब्जेक्ट के पास केवल एक लावल्यू एक्सप्रेशन द्वारा अभिगम किए गए अपने संग्रहीत मूल्य होगा जो निम्नलिखित प्रकारों में से एक है 73) या 88) :

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

73) या 88) इस सूची का इरादा उन परिस्थितियों को निर्दिष्ट करना है जिसमें कोई ऑब्जेक्ट या उपनाम नहीं हो सकता है

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

जैसा कि डग टी द्वारा लिखा गया है, यह एक सरल परीक्षण मामला है, जो शायद इसे जीसीसी के साथ ट्रिगर करता है:

check.c

 #include <stdio.h> void check(short *h,long *k) { *h=5; *k=6; if (*h == 5) printf("strict aliasing problem\n"); } int main(void) { long k[1]; check((short *)k,k); return 0; } 

gcc -O2 -o check check.c साथ संकलित करें आमतौर पर (अधिकांश जीसीसी संस्करणों के साथ मैंने कोशिश की थी) यह आउटपुट "सख्त अलियासिंग समस्या" है, क्योंकि कंपाइलर मानता है कि "चेक" फ़ंक्शन में "कश्मीर" के समान पते नहीं हो सकते। इस कारण कि कंपाइलर if (*h == 5) दूर करता है और हमेशा printf को कॉल करता है

जिन लोगों के लिए यहां दिलचस्पी है, वे एक्स 64 कोडर कोड हैं, जो जीसीसी 4.6.3 द्वारा उत्पादित है, जो एक्स 64 के लिए उबुंटू 12.04.2 पर चल रहा है:

 movw $5, (%rdi) movq $6, (%rsi) movl $.LC0, %edi jmp puts 

तो अगर हालत पूरी तरह से कोडांतरक कोड से चली गई है।

पॉइंटर कॉस्ट के माध्यम से दंड का प्रकार (एक संघ का उपयोग करने के लिए विरोध के रूप में) सख्त अलियासिंग को तोड़ने का एक प्रमुख उदाहरण है।

सख्त अलियासिंग एक ही डेटा में विभिन्न सूचक प्रकार की अनुमति नहीं दे रहा है।

इस अनुच्छेद से आप पूरी तरह से इस मुद्दे को समझने में सहायता कर सकते हैं।

सी 8 9 के तर्क के मुताबिक, मानक के लेखकों को ऐसा कोड देना नहीं चाहते थे जैसे कोड दिए गए हैं:

 int x; int test(double *p) { x=5; *p = 1.0; return x; } 

को असाइनमेंट और रिटर्न स्टेटमेंट के बीच x के मान को पुनः लोड करने की आवश्यकता होनी चाहिए ताकि p की संभावना को अनुमति दें, और *p के असाइनमेंट के परिणामस्वरूप x के मान को बदल दिया जाए। धारणा है कि एक कंपाइलर को यह अनुमान लगाने का हकदार होना चाहिए कि ऊपर की तरह स्थितियों में अलियासिंग न हो , जो गैर-विवादास्पद था।

स्टैंडर्ड के लेखकों ने कुछ मामलों की पहचान की है जहां अलियासिंग का उपयोग कोड में किया जा सकता है जो लगभग 100% पोर्टेबल होना चाहिए , और अनिवार्य है कि कंपाइलर्स कम से कम उन मामलों में अलियासिंग के लिए अनुमति देते हैं। उन्होंने कोई भी निर्णय नहीं करने का प्रयास किया कि क्या कोड के भीतर प्रयोग करने योग्य हो, जो केवल विशिष्ट प्लेटफार्मों पर प्रयोग करने योग्य है, न ही गुणवत्ता के कार्यान्वयन से उन संरचनाओं का समर्थन किया जाना चाहिए जो उन प्लेटफार्मों पर सिस्टम प्रोग्रामिंग के लिए उपयुक्त होने का दावा करते हैं।

यदि किसी विशेष प्लेटफ़ॉर्म के लिए एक कंपाइलर इंगित करता है कि यह उच्च अंत संख्या crunching अनुप्रयोगों के लिए लक्षित है, और उस संकलक के लिए खिलाया है कि उस मंच malfunctions के लिए ऑपरेटिंग सिस्टम कोड का एक टुकड़ा, इसका मतलब यह नहीं है कि संकलक दोषपूर्ण है, और न ही इसका मतलब यह है कि कोड दोषपूर्ण है। इसका केवल मतलब है कि कंपाइलर और ऑपरेटिंग सिस्टम कोड एक दूसरे के साथ उपयोग के लिए उपयुक्त नहीं हैं।

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