कक्षाओं में आसन्न सदस्यों के ओवरलैपिंग को क्या रोकता है?


12

निम्नलिखित तीन structएस पर विचार करें :

class blub {
    int i;
    char c;

    blub(const blub&) {}
};

class blob {
    char s;

    blob(const blob&) {}
};

struct bla {
    blub b0;
    blob b1;
};

विशिष्ट प्लेटफार्मों पर जहां int4 बाइट्स हैं, आकार, संरेखण और कुल पैडिंग 1 इस प्रकार हैं:

  struct   size   alignment   padding  
 -------- ------ ----------- --------- 
  blub        8           4         3  
  blob        1           1         0  
  bla        12           4         6  

के भंडारण blubऔर blobसदस्यों के बीच कोई ओवरलैप नहीं है , भले ही आकार 1 के blobसिद्धांत में "फिट" हो सकता है blub

C ++ 20 उस no_unique_addressविशेषता का परिचय देता है, जो आसन्न खाली सदस्यों को समान पता साझा करने की अनुमति देता है। यह स्पष्ट रूप से एक सदस्य की गद्दी का उपयोग करके ऊपर वर्णित परिदृश्य को दूसरे को संग्रहीत करने की अनुमति देता है। से cppreference (जोर मेरा):

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

वास्तव में, यदि हम इस विशेषता का उपयोग करते हैं, तो blub b0इसका आकार घटbla जाता है 8, इसलिए blobइसे वास्तव में blub गॉडबोल्ट के अनुसार देखा जाता है

अंत में, हम अपने सवाल पर आते हैं:

मानकों में क्या पाठ (C ++ 20 के माध्यम से C ++ 11) इस ओवरलैपिंग को बिना no_unique_addressउन वस्तुओं के लिए रोकता है , जो तुच्छ रूप से कॉपी करने योग्य नहीं हैं?

मुझे ऊपर से तुच्छ रूप से कॉपी करने योग्य (टीसी) ऑब्जेक्ट्स को बाहर करने की आवश्यकता है, क्योंकि टीसी ऑब्जेक्ट्स के लिए, यह std::memcpyएक ऑब्जेक्ट से दूसरे ऑब्जेक्ट में शामिल है, जिसमें सदस्य सबोबिज भी शामिल हैं, और अगर स्टोरेज ओवरलैप किया गया था, तो यह टूट जाएगा (क्योंकि सभी या स्टोरेज का हिस्सा आसन्न सदस्य के लिए अधिलेखित किया जाएगा) 2


1 हम पैडिंग की गणना केवल संरचना के आकार और उसके सभी घटक सदस्यों के आकार के बीच अंतर के रूप में करते हैं।

2 यही कारण है कि मेरे पास कॉपी कंस्ट्रक्टर्स परिभाषित हैं: बनाने blubऔर तुच्छ रूप से कॉपी करने के लिए blobनहीं ।


मैंने इस पर शोध नहीं किया है, लेकिन मैं "मानो" नियम का अनुमान लगा रहा हूं । अगर सार मशीन (जो आपके कोड के खिलाफ संकलित है) के लिए कोई अवलोकन अंतर (बहुत विशिष्ट अर्थ btw के साथ एक शब्द) है, तो संकलक कोड को बदल सकता है, हालांकि इसे पसंद करता है।
जेसपर जुहल

बहुत यकीन है कि यह इस का एक प्रकार है: stackoverflow.com/questions/53837373/…
NathanOliver

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

1
@BeeOnRope मैं आपके प्रश्न का उत्तर नहीं दे सकता, क्षमा करें। यही कारण है कि मैंने सिर्फ एक टिप्पणी पोस्ट की है और एक उत्तर नहीं। उस टिप्पणी में आपको जो मिला वह एक स्पष्टीकरण के प्रति मेरा सबसे अच्छा अनुमान था, लेकिन मुझे इसका जवाब नहीं पता है (यह जानने के लिए खुद को जानने की जिज्ञासा है - यही वजह है कि आपको उत्थान मिला है)।
जेस्पर जुहल

1
@ निकोलबोलस - क्या आप सही सवाल का जवाब दे रहे हैं? यह सुरक्षित प्रतियों या कुछ और का पता लगाने के बारे में नहीं है। बल्कि मैं उत्सुक हूं कि सदस्यों के बीच पैडिंग का फिर से उपयोग क्यों नहीं किया जा सकता है। किसी भी मामले में, आप गलत हैं: तुच्छ रूप से प्रतिलिपि प्रकार का एक गुण है और हमेशा रहा है। हालाँकि, किसी ऑब्जेक्ट को सुरक्षित रूप से कॉपी करने के लिए दोनों में एक टीसी प्रकार (प्रकार की संपत्ति) होना चाहिए, और एक संभावित ओवरलैपिंग-विषय (ऑब्जेक्ट की एक संपत्ति, जो मुझे लगता है कि आप भ्रमित हो गए हैं) नहीं होना चाहिए। अभी भी पता नहीं है कि हम यहां थोपों के बारे में क्यों बात कर रहे हैं।
मधुमक्खी पालन

जवाबों:


1

मेमोरी मॉडल के बारे में बात करते समय मानक भयानक रूप से शांत होता है और इसके उपयोग की कुछ शर्तों के बारे में बहुत स्पष्ट नहीं है। लेकिन मुझे लगता है कि मुझे एक काम करने का तर्क मिला (जो थोड़ा कमजोर हो सकता है)

सबसे पहले, आइए जानें कि किसी वस्तु का क्या हिस्सा है। [basic.types] / 4 :

ऑब्जेक्ट का ऑब्जेक्ट का प्रतिनिधित्व प्रकार Tके N unsigned charऑब्जेक्ट द्वारा लिया गया ऑब्जेक्ट का अनुक्रम है T, जहां Nबराबर होता है sizeof(T)। एक प्रकार की वस्तु का मूल्य प्रतिनिधित्व Tबिट्स का सेट है जो प्रकार के मूल्य का प्रतिनिधित्व करने में भाग लेता है T। ऑब्जेक्ट प्रतिनिधित्व में बिट्स जो मान प्रतिनिधित्व का हिस्सा नहीं हैं वे बिटिंग पैडिंग हैं।

तो की वस्तु प्रतिनिधित्व b0के होते हैं sizeof(blub) unsigned charवस्तुओं, इसलिए 8 बाइट्स। पैडिंग बिट्स ऑब्जेक्ट का हिस्सा हैं।

कोई वस्तु दूसरे के स्थान पर कब्जा नहीं कर सकती है यदि वह उसके भीतर निहित नहीं है [basic.life] /1.5 :

एक oप्रकार की वस्तु का जीवनकाल Tतब समाप्त होता है जब:

[...]

(१.५) वह संग्रहण जो ऑब्जेक्ट पर कब्जा करता है, जारी किया जाता है, या उस ऑब्जेक्ट द्वारा पुन: उपयोग किया जाता है जो भीतर oनिहित नहीं है ([intro.object])।

तो जीवनकाल b0समाप्त हो जाएगा, जब उस पर कब्जा करने वाले भंडारण को किसी अन्य ऑब्जेक्ट द्वारा पुन: उपयोग किया जाएगा, अर्थात b1। मैंने इसकी जाँच नहीं की है, लेकिन मुझे लगता है कि मानक यह कहता है कि किसी वस्तु का सबबजेक्ट जो जीवित है, वह भी जीवित होना चाहिए (और मैं कल्पना नहीं कर सकता कि यह कैसे अलग तरीके से काम करना चाहिए)।

भंडारण कि इतने b0 में रह रहे हैं द्वारा नहीं किया जा सकता है b1। मुझे मानक में "कब्जा" की कोई परिभाषा नहीं मिली है, लेकिन मुझे लगता है कि एक उचित व्याख्या "वस्तु प्रतिनिधित्व" का हिस्सा होगी। ऑब्जेक्ट प्रतिनिधित्व का वर्णन करने वाले उद्धरण में, "टेक अप" शब्द का उपयोग किया जाता है 1 । यहां, यह 8 बाइट्स होगा, इसलिए blaकम से कम एक के लिए और अधिक की आवश्यकता है b1

विशेष रूप से सबोबिज के लिए (इसलिए अन्य गैर-स्थैतिक डेटा सदस्यों के बीच) भी वजीफा [intro.object] / 9 है (लेकिन यह C ++ 20, thx @BeeOnRope के साथ जोड़ा गया था)

ओवरलैपिंग जीवनकाल वाली दो वस्तुएं जो बिट-फ़ील्ड नहीं हैं, एक ही पता हो सकता है यदि एक दूसरे के भीतर नेस्टेड है, या यदि कम से कम एक शून्य आकार का सबोबेज है और वे विभिन्न प्रकार के हैं; अन्यथा, उनके पास अलग-अलग पते हैं और भंडारण के असमान बाइट्स पर कब्जा है

(जोर मेरा) यहां फिर से, हमारे पास समस्या है कि "कब्जा" परिभाषित नहीं है और फिर से मैं ऑब्जेक्ट प्रतिनिधित्व में बाइट्स लेने का तर्क दूंगा। ध्यान दें कि इसमें एक फुटनोट है [basic.memobj] / footnote 29

"As-if" नियम के तहत एक कार्यान्वयन को एक ही मशीन के पते पर दो ऑब्जेक्ट को स्टोर करने या ऑब्जेक्ट को स्टोर करने की अनुमति नहीं है यदि प्रोग्राम अंतर नहीं देख सकता है ([intro.execution])।

जो संकलक को इसे तोड़ने की अनुमति दे सकता है यदि यह साबित कर सकता है कि कोई अवलोकन योग्य प्रभाव नहीं है। मुझे लगता है कि यह ऑब्जेक्ट लेआउट जैसी मूलभूत चीज़ के लिए बहुत जटिल है। शायद इसीलिए यह अनुकूलन केवल तब लिया जाता है जब उपयोगकर्ता यह जानकारी प्रदान करता है कि [no_unique_address]विशेषता को जोड़कर वस्तुओं को असम्बद्ध करने का कोई कारण नहीं है ।

tl; dr: पैडिंग शायद ऑब्जेक्ट का हिस्सा है और सदस्यों को निराश होना पड़ता है।


1 मैं एक संदर्भ को जोड़ने का विरोध नहीं कर सकता था जिसे लेने का मतलब हो सकता है: वेबस्टर का संशोधित अनिर्धारित शब्दकोश, जी। एंड सी। मेरियम, 1913 (जोर मेरा)

  1. के आयामों को पकड़ना या भरना; के कमरे या जगह लेने के लिए; भरने या भरने के लिए; जैसा कि, शिविर में पाँच एकड़ जमीन है। सर जे। हर्शल

शब्दकोश क्रॉल के बिना कौन सा मानक क्रॉल पूरा होगा?


2
"स्टोरेज डिस्ट्रॉफ़ बाइट्स ऑफ़ स्टोरेज" भाग से। कॉस्टॉरेज पर्याप्त होगा, मुझे लगता है, मेरे लिए - लेकिन यह शब्द केवल C ++ 20 में बदलाव के भाग के रूप में जोड़ा गया था no_unique_address। यह C ++ 20 से पहले की स्थिति को कम स्पष्ट करता है। मुझे समझ में नहीं आया कि आपका तर्क "कोई वस्तु किसी दूसरे के स्थान पर कब्जा नहीं कर सकती है यदि वह मूल रूप से" नेस्टेड नहीं है "तो basic.life/1.5 से, विशेष रूप से कैसे प्राप्त करें" संग्रहण जो ऑब्जेक्ट जारी होता है "से "कोई भी वस्तु दूसरे के स्थान पर कब्जा नहीं कर सकती है"।
मधुमक्खी पालन

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

"अतिव्यापी जीवनकाल वाली दो वस्तुएं जो बिट-फ़ील्ड नहीं हैं, एक ही पता हो सकता है यदि एक दूसरे के भीतर नेस्टेड है, या यदि कम से कम एक शून्य आकार का सब -जेक्ट है और वे विभिन्न प्रकार के हैं" 2 ऑब्जेक्ट्स ओवरलैपिंग लाइफटाइम के साथ एक ही प्रकार, एक ही पता
भाषा वकील

क्षमा करें, क्या आप विस्तृत कर सकते हैं? आप मेरे उत्तर से एक मानक उद्धरण उद्धृत कर रहे हैं और एक उदाहरण ला रहे हैं जो उस के साथ थोड़ा संघर्ष करता है। मैं अनिश्चित हूं कि क्या यह मेरे उत्तर पर टिप्पणी है और यदि यह है तो मुझे यह बताना चाहिए। आपके उदाहरण के बारे में मैं यह कहूंगा कि किसी को मानक के अन्य भागों पर विचार करना होगा (किसी अन्य ऑब्जेक्ट के लिए भंडारण प्रदान करने वाले एक अहस्ताक्षरित चार सरणी के बारे में एक पैराग्राफ है, शून्य आकार के आधार अनुकूलन के बारे में कुछ और अभी भी आगे भी देखना चाहिए कि क्या प्लेसमेंट नया है विशेष भत्ते, सभी चीजें जो मुझे नहीं लगता कि ओपी उदाहरण के लिए प्रासंगिक हैं)
n314159

@ n314159 मुझे लगता है कि यह शब्द दोषपूर्ण हो सकता है।
भाषा वकील
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.