दिलचस्प पोस्ट
मैं वेबपेज में जावास्क्रिप्ट कोड कैसे छिपा सकता हूं? मैं एक जावा एप्लिकेशन कैसे लिख सकता हूं जो खुद रनटाइम पर अपडेट कर सकता है? एचटीएमएल 5 कैनवास में क्रॉस-मूल डेटा जावास्क्रिप्ट के साथ, क्या मैं एक एसवीजी <g> तत्व की जेड इंडेक्स / परत बदल सकता हूँ? ClearCase में, मैं एक फ़ाइल के पुराने संस्करण को एक स्थिर दृश्य में कैसे देख सकता हूँ, कमांड लाइन से? सी # प्रकार पर स्विच क्या एक इकाई निकाय अनुरोध एक HTTP डिलीएट अनुरोध के लिए है? एंड्रॉइड में एक कैनवास को बिटमैप छवि में परिवर्तित करना क्यूरींग सी ++ में कैसे किया जा सकता है? जावास्क्रिप्ट का उपयोग करते हुए पीडीएफ HTML से div में उत्पन्न करें "Href" के लिए html में एक फ़ॉरवर्ड स्लैश के साथ प्रारंभ करना आर + जीजीप्लोट: एकाधिक पृष्ठों पर प्लॉटिंग त्रुटि: सेटअप स्क्रिप्ट त्रुटि से बाहर निकल गई: कमांड 'x86_64-linux-gnu-gcc' से बाहर निकलने की स्थिति 1 में विफल शिफ्ट को हटाने के लिए व्याकरण को सुधारना अगर-तब-दूसरे में संघर्ष कम हो क्या आईओएस में गोपनीयता सेटिंग्स रीसेट करना संभव है?

सी ++ क्लास का आकार कैसे निर्धारित किया जाता है?

सारांश : कंपाइलर संकलन के दौरान सी ++ क्लास के आकार को स्थिर रूप से कैसे तय करता है?

विवरण :

मैं यह समझने की कोशिश कर रहा हूं कि नियम किस वर्ग की उपयोगिता की स्मृति का उपयोग करेगा, और यह भी कि स्मृति कैसे गठबंधन होगी।

उदाहरण के लिए निम्नलिखित कोड 4 वर्ग घोषित करता है। पहले 2 प्रत्येक 16 बाइट्स हैं। लेकिन 3 48 बाइट्स हैं, भले ही इसमें पहले 2 के रूप में समान आंकड़े शामिल हों। जबकि चौथी कक्षा में एक ही डेटा सदस्यों को तीसरे स्थान पर रखा गया है, लेकिन यह 32 बाइट्स है।

#include <xmmintrin.h> #include <stdio.h> class TestClass1 { __m128i vect; }; class TestClass2 { char buf[8]; char buf2[8]; }; class TestClass3 { char buf[8]; __m128i vect; char buf2[8]; }; class TestClass4 { char buf[8]; char buf2[8]; __m128i vect; }; TestClass1 *ptr1; TestClass2 *ptr2; TestClass3 *ptr3; TestClass4 *ptr4; int main() { ptr1 = new TestClass1(); ptr2 = new TestClass2(); ptr3 = new TestClass3(); ptr4 = new TestClass4(); printf("sizeof TestClass1 is: %lu\t TestClass2 is: %lu\t TestClass3 is: %lu\t TestClass4 is: %lu\n", sizeof(*ptr1), sizeof(*ptr2), sizeof(*ptr3), sizeof(*ptr4)); return 0; } 

मुझे पता है कि इस उत्तर में क्लास के डेटा सदस्यों के संरेखण के साथ कुछ करना है। लेकिन मैं यह समझने की कोशिश कर रहा हूं कि ये नियम क्या हैं और संकलन चरणों के दौरान उनका उपयोग कैसे किया जाता है क्योंकि मेरे पास एक क्लास है जो __m128i डाटा सदस्य है, लेकिन डेटा सदस्य 16-बाइट संरेखित नहीं है और यह एक सेगफ़ॉल्ट में परिणाम है जब कंपाइलर डेटा एक्सेस करने के लिए movaps का इस्तेमाल करते हुए कोड उत्पन्न करता है।

वेब के समाधान से एकत्रित समाधान "सी ++ क्लास का आकार कैसे निर्धारित किया जाता है?"

पीओडी (सादे पुराने डेटा) के लिए, नियम आम तौर पर हैं:

  • संरचना में प्रत्येक सदस्य के कुछ आकार और कुछ संरेखण आवश्यकताएं एक हैं।
  • कंपाइलर आकार एस से शून्य पर सेट होता है और एक संरेखण आवश्यकता एक सेट (बाइट) के साथ।
  • कंपाइलर संरचना में प्रत्येक सदस्य को क्रमबद्ध करता है:
    1. सदस्य संरेखण की आवश्यकता पर विचार करें। यदि S वर्तमान में एक के कई नहीं है, तो बस पर्याप्त बाइट एस जोड़ें ताकि यह एक के एक बहु है। यह निर्धारित करता है कि सदस्य कहां जाएंगे; यह ऑफसेट एस पर संरचना की शुरुआत से (एस के वर्तमान मूल्य के लिए) पर जाएंगे।
    2. ए और ए के कम से कम सामान्य एकाधिक को सेट करें।
    3. सदस्य के लिए जगह अलग सेट करने के लिए एस में एस जोड़ें।
  • जब प्रत्येक सदस्य के लिए उपरोक्त प्रक्रिया पूरी की जाती है, तो संरचना की संरेखण की आवश्यकता पर विचार करें ए। यदि एस वर्तमान में ए के एक से अधिक नहीं है, तो एस के लिए केवल पर्याप्त जोड़ें ताकि यह ए के एक गुणक हो।

संरचना का आकार एस के मूल्य है जब ऊपर किया जाता है।

इसके अतिरिक्त:

  • यदि कोई सदस्य एक सरणी है, तो इसका आकार प्रत्येक तत्व के आकार से गुणा करने वाले तत्वों की संख्या है, और इसके संरेखण की आवश्यकता एक तत्व की संरेखण आवश्यकता है।
  • यदि कोई सदस्य एक संरचना है, तो इसके आकार और संरेखण की आवश्यकता को ऊपर की गणना की जाती है।
  • यदि कोई सदस्य एक संघ है:
    1. सबसे बड़ी सदस्य के आकार में एस सेट करें
    2. सभी सदस्यों के संरेखण के कम से कम सामान्य बहु के लिए सेट करें।
    3. यदि एस ए के एक बहु नहीं है, तो ए के बराबर को जोड़ने के लिए ए के बहुत से जोड़ें।

अपने TestClass3 पर विचार करें:

  • एस 0 से शुरू होता है और 1 से शुरू होता है
  • char buf[8] 8 बाइट्स और संरेखण 1 की आवश्यकता होती है, इसलिए एस 8 से 8 तक बढ़ जाता है, और ए 1 बकाया रहता है।
  • __m128i vect 16 बाइट्स और संरेखण की आवश्यकता है 16. सबसे पहले, सही संरेखण देने के लिए एस को 16 तक बढ़ाया जाना चाहिए। फिर ए को 16 तक बढ़ाया जाना चाहिए। फिर एस को vect लिए जगह बनाने के लिए 16 की बढ़ोतरी होनी चाहिए, इसलिए अब एस 32 है।
  • char buf2[8] 8 बाइट्स और संरेखण 1 की आवश्यकता होती है, इसलिए एस 8 से 24 तक बढ़ जाता है, और ए char buf2[8] 16 होता है।
  • अंत में, एस 24 है, जो ए (16) का एक बहुमूल्य नहीं है, इसलिए एस को 8 से 32 तक बढ़ाया जाना चाहिए।

तो TestClass3 का आकार 32 बाइट्स है

प्राथमिक प्रकार ( int , double , एट वगैरह) के लिए, संरेखण आवश्यकताओं का कार्यान्वयन निर्भर है और बड़े पैमाने पर हार्डवेयर द्वारा निर्धारित किया जाता है। कई प्रोसेसरों पर, जब यह एक निश्चित संरेखण (आमतौर पर जब मेमोरी में उसका पता उसके आकार का एक बड़ा होता है) डेटा लोड और संग्रहित करने के लिए तेज़ होता है इसके अलावा, ऊपर दिए गए नियम तर्क से काफी हद तक अनुसरण करते हैं; वे प्रत्येक सदस्य को लगाते हैं जहां आवश्यक से अधिक स्थान का उपयोग किए बिना संरेखण आवश्यकताओं को पूरा करना आवश्यक है।

यह पूरी तरह से संकलक पर निर्भर करता है कि किसी वर्ग के आकार का निर्धारण कैसे किया जाता है। एक संकलक आमतौर पर एक निश्चित एप्लिकेशन बाइनरी इंटरफ़ेस से मेल खाने के लिए संकलित होता है, जो कि प्लेटफॉर्म पर निर्भर होता है।

आपके द्वारा देखे गए व्यवहार, हालांकि, बहुत विशिष्ट है कंपाइलर सदस्यों को संरेखित करने की कोशिश कर रहा है ताकि वे प्रत्येक अपने आकार के एक से अधिक की शुरुआत करें। TestClass3 के मामले में, सदस्यों में से एक प्रकार __m128i और sizeof(__m128i) == 16 तो यह उस सदस्य को एक बाइट से शुरू करने की कोशिश करेगी जो कि 16 का एक बहुमूल्य है। पहला सदस्य टाइप char[8] तो 8 बाइट्स ऊपर ले जाता है। यदि संकलक को पहले सदस्य के बाद सीधे _m128i ऑब्जेक्ट _m128i होता है, तो यह स्थिति 8 पर शुरू होगा, जो कि 16 के एक से अधिक नहीं है:

 0 8 16 24 32 48 ┌───────────────┬───────────────────────────────┬───────────────┬┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄ │ char[8] │ __m128i │ char[8] │ └───────────────┴───────────────────────────────┴───────────────┴┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄ 

इसलिए इसके बजाय यह ऐसा करना पसंद करता है:

 0 8 16 24 32 48 ┌───────────────┬┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┬───────────────────────────────┬───────────────┐┄┄┄ │ char[8] │ │ __m128i │ char[8] │ └───────────────┴┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┴───────────────────────────────┴───────────────┘┄┄┄ 

यह इसे 48 बाइट्स का आकार देता है।

जब आप TestClass4 प्राप्त करने के लिए सदस्यों को पुन: क्रमित करते हैं तो लेआउट बन जाता है:

 0 8 16 24 32 48 ┌───────────────┬───────────────┬───────────────────────────────┬┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄ │ char[8] │ char[8] │ __m128i │ └───────────────┴───────────────┴───────────────────────────────┴┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄ 

अब सब कुछ सही ढंग से गठबंधन कर दिया गया है – सरणियों ऑफसेट्स में 1 (उनके तत्वों के आकार) के एकाधिक होते हैं और __m128i ऑब्जेक्ट ऑफ़सेट पर होता है जो कि 16 का एक __m128i है – और कुल आकार 32 बाइट्स हैं।

कारण संकलक स्वयं इस पुनर्व्यवस्था को नहीं करता है, क्योंकि मानक निर्दिष्ट करता है कि बाद में क्लास के सदस्यों के पास अधिक पते होने चाहिए:

समान अभिगम नियंत्रण (खंड 11) के साथ एक (गैर-यूनियन) वर्ग के गैर-स्थिर डेटा सदस्यों को आवंटित किया जाता है ताकि बाद के सदस्यों को कक्षा ऑब्जेक्ट के भीतर अधिक पते हो।

नियमों को प्रयोग में आवेदन बाइनरी इंटरफ़ेस विनिर्देश द्वारा पत्थर में सेट किया गया है, जो कि इस इंटरफेस को साझा करने वाले कार्यक्रमों के लिए विभिन्न प्रणालियों के बीच संगतता सुनिश्चित करता है।

जीसीसी के लिए, यह इटेनियम एबीआई है I

(दुर्भाग्यवश यह अब सार्वजनिक रूप से उपलब्ध नहीं है, हालांकि मुझे एक दर्पण मिला है ।)

यदि आप आवंटन को सुनिश्चित करना चाहते हैं, तो आपको इस पोस्ट पर "एचडी फ़ाइल" में "प्रोगा पैक (1)" का उपयोग करना चाहिए: http://tedlogan.com/techblog2.html