2009-02-13 15 views
8

इन प्रकार पर विचार करें:क्या जीसीसी कॉन्फ़िगर करने योग्य में "खाली आधार अनुकूलन" है?

struct A {}; 
    struct B : A { int i; }; 

sizeof(A) > 0 के रूप में मानक के लिए आवश्यक।

sizeof(B) खाली आधार अनुकूलन के कारण 4 होना चाहिए। फिर भी जीसीसी 4.1.1 पर यह 5 है (मैं इस क्षेत्र में 1 का पैक उपयोग कर रहा हूं)। और असंगत रूप से - मेरी कुछ फाइलें इसे प्राप्त कर रही हैं, कुछ नहीं हैं। यह सुनिश्चित नहीं हो सकता कि मतभेद अभी तक क्या हैं, हमारे पास एक बड़ा प्रजनन है।

अन्य तीन कंपाइलर्स पर मैं (माइक्रोसॉफ्ट और फ्रीस्केल द्वारा) उपयोग कर रहा हूं, मुझे यह समस्या नहीं है। this article के अनुसार खाली आधार अनुकूलन वैकल्पिक रूप से वैकल्पिक है।

क्या जीसीसी 4.1.1 में इसे ट्यून करने के लिए कोई संकलक विकल्प या प्रगति है? मैं इस मुद्दे के आसपास काम कर सकता हूं लेकिन मैं समझना चाहता हूं कि पहले क्या हो रहा है। मैं थोड़ी देर के लिए googled और कुछ भी नहीं लग रहा है।

उत्तर

10

यह हमेशा होता है। मैं इसे समझने से पहले तुरंत पोस्ट करता हूं। हो सकता है कि पोस्टिंग का कार्य मुझे एक अलग तरीके से सोचता है ..

तो मेरे प्रश्न में नमूना थोड़ा अधिक सरलीकृत था। यह वास्तव में अधिक इस तरह है:

struct Base {}; 
struct C1 : Base { int i; } 
struct C2 : Base { C1 c; int i; } 

sizeof (सी 1) सही ढंग से 4 सभी प्लेटफार्मों पर है, लेकिन sizeof (C2) जीसीसी पर 9 के बजाय 8 है। और ... जाहिर है कि जीसीसी एकमात्र चीज है जो मूल प्रश्न में लिखे आलेख के आखिरी बिट के मुताबिक सही हो जाती है। मैं इसे उद्धृत करूंगा (नाथन मेयर्स से):

संबंधित "रिक्त सबोबजेक्ट" अनुकूलन का पूरा परिवार संभव है, एबीआई विनिर्देशों के अधीन एक कंपाइलर को अवश्य देखना चाहिए। (जेसन मेरिल ने मुझे कुछ साल पहले मेरे बारे में बताया था।) उदाहरण के लिए, ए, बी, और सी के तीन स्ट्रक्चर सदस्यों और चौथे गैर-खाली पर विचार करें। वे, अनुरूप रूप से, सभी एक ही पते पर कब्जा कर सकते हैं, जब तक कि उनके पास एक दूसरे के साथ या युक्त वर्ग के साथ समान आधार नहीं है। अभ्यास में एक आम गोचा कक्षा के समान खाली आधार से प्राप्त कक्षा के पहले (या केवल) सदस्य होना है। कंपाइलर को पैडिंग डालना पड़ता है ताकि वे दो उप-विषयों के अलग-अलग पते हों। यह वास्तव में इटरेटर एडेप्टर में होता है जिसमें एक इंटरैटर सदस्य होता है, दोनों std :: iterator से व्युत्पन्न होते हैं। एक सावधानीपूर्वक लागू मानक मानक std :: reverse_iterator इस समस्या को प्रदर्शित कर सकता है।

तो, मैं जो असंगतता देख रहा था वह केवल उन मामलों में था जहां मेरे ऊपर उपरोक्त पैटर्न था। एक खाली संरचना से प्राप्त होने वाली हर दूसरी जगह ठीक थी।

आसपास काम करने के लिए काफी आसान है। टिप्पणियों और उत्तरों के लिए सभी को धन्यवाद।

नोट:: __attribute__((__packed__)) या डिफ़ॉल्ट पैकिंग इन नियमों को संशोधित करेगा बदलते

+1

इंटेल कंपाइलर इसे सही और साथ ही जीसीसी भी प्राप्त करता है। एमएसवीसी अतिसंवेदनशील है और खाली आधार अनुकूलन पर मानकों का उल्लंघन करता है जब आधार वर्गों में से एक भी पहले सदस्य का आधार वर्ग है। मैंने वीसी ++ (2005/2008) और जीसीसी (4.1.1) खाली-बेस नियमों के लिए बहुत अधिक नियम पोस्ट किए हैं। http://stackoverflow.com/questions/547290/is-the-empty-base-optimization-in-gcc-configurable/919694#919694 – Adisak

0

अच्छा, यह एक पूर्ण उत्तर नहीं है, लेकिन GCC Manual का उल्लेख है कि जी ++ कभी-कभी गलत ऑफसेट पर खाली बेस कक्षाएं रख सकता है। -Wabi विकल्प के बारे में थोड़ा सा देखें।

1

जीसीसी सी ++ मानक गद्दी के साथ इन नियमों का पालन करती।

  • कक्षा एम्प्टीबेस {}; -> sizeof (EmptyBase) == 1

  • किसी भी प्रकार के रिक्त-आधार संरचना ऑफ़सेट में 0 तक मैप किए जाएंगे जब तक कि सभी अद्वितीय प्रकार (parenting सहित) हैं।

  • गैर खाली-बेस माता-पिता केवल संरेखण के लिए केवल पैडिंग के साथ घोषित आदेश में हैं।

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

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

  • रिक्त वर्ग वाले सदस्य जो कक्षा में कम से कम एक बाइट स्टोरेज लेते हैं।


MSVC++ इन नियमों का पालन करती:

नोट: #pragma pack या डिफ़ॉल्ट पैकिंग इन नियमों को संशोधित करेगा बदलते।

  • कक्षा एम्प्टीबेस {}; -> आकार (एम्प्टीबेस) == 1

  • एक खाली-बेस क्लास (या खाली-बेस से प्राप्त कक्षा) ऑफसेट 0 (शून्य) से शुरू होने वाला एकमात्र तरीका यह है कि यह पहली बेस क्लास है।

  • एक गैर-खाली-बेस क्लास बेस क्लास के लिए अगले मान्य संरेखण ऑफसेट पर शुरू होगी।

  • सभी रिक्त-बेस वर्गों को व्युत्पन्न कक्षा में शून्य प्रभावी भंडारण दिखाई देगा और वर्तमान ऑफसेट को तब तक प्रभावित नहीं करेगा जब तक कि किसी अन्य खाली-बेस क्लास (या खाली-आधार से प्राप्त कक्षा) के बाद, निम्नलिखित नियम देखना चाहिए।

  • खाली-खाली वर्ग (या रिक्त आधार से प्राप्त कक्षा) जो एक खाली-बेस वर्ग (या खाली-आधार से प्राप्त कक्षा) का पालन करता है, वर्तमान में पैडिंग से पहले मौजूदा ऑफसेट स्थिति में 1 जोड़ देगा कक्षा के लिए संरेखण।

  • अंतिम बेस क्लास और प्रथम श्रेणी के सदस्य या वीएफटी-पॉइंटर के बीच कोई पैडिंग (संरेखण के अलावा) नहीं है। *** नोट: यह एक अति आक्रामक खाली-आधार-अनुकूलन है जो सी ++ मानक को तोड़ सकता है।

  • रिक्त वर्ग वाले सदस्य जो कक्षा में कम से कम एक बाइट स्टोरेज लेते हैं।

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