C में ओवरलैपिंग ऑब्जेक्ट्स के शब्दार्थ क्या हैं?


25

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

struct s {
  int a, b;
};

आमतौर पर 1 , इस संरचना का आकार 8 और संरेखण 4 होगा।

क्या होगा अगर हम दो struct sऑब्जेक्ट बनाते हैं (अधिक सटीक रूप से, हम आवंटित दो ऐसी वस्तुओं में लिखते हैं), दूसरा ऑब्जेक्ट पहले ओवरलैपिंग के साथ?

char *storage = malloc(3 * sizeof(struct s));
struct s *o1 = (struct s *)storage; // offset 0
struct s *o2 = (struct s *)(storage + alignof(struct s)); // offset 4

// now, o2 points half way into o1
*o1 = (struct s){1, 2};
*o2 = (struct s){3, 4};

printf("o2.a=%d\n", o2->a);
printf("o2.b=%d\n", o2->b);
printf("o1.a=%d\n", o1->a);
printf("o1.b=%d\n", o1->b);

क्या इस कार्यक्रम के बारे में कुछ भी अपरिभाषित व्यवहार नहीं है? यदि हां, तो यह अपरिभाषित कहां हो जाता है? यदि यह यूबी नहीं है, तो क्या यह हमेशा निम्नलिखित प्रिंट करने की गारंटी है:

o2.a=3
o2.b=4
o1.a=1
o1.b=3

विशेष रूप से, मुझे पता है कि क्या द्वारा वस्तु की ओर इशारा करने के लिए होता चाहते हैं o1जब o2, जो यह ओवरलैप करता है, लिखा है। यह अभी भी unclobbered हिस्सा (का उपयोग करने की अनुमति दी है o1->a)? क्या क्लॉबर्ड वाले हिस्से o1->bको एक्सेस करना बिल्कुल वैसा ही है o2->a?

प्रभावी प्रकार यहां कैसे लागू होता है? जब आप अति-ओवरलैपिंग ऑब्जेक्ट्स और पॉइंटर्स के बारे में बात कर रहे हों तो नियम काफी स्पष्ट होते हैं जो आखिरी स्टोर के समान स्थान की ओर इशारा करते हैं, लेकिन जब आप वस्तुओं के प्रभावी प्रकार के हिस्सों या ओवरलैपिंग ऑब्जेक्ट्स के बारे में बात करना शुरू करते हैं तो यह कम स्पष्ट होता है।

दूसरा लेखन एक अलग प्रकार का होता तो क्या कुछ बदल जाता? यदि सदस्य कहते थे intऔर shortदो के बजाय int?

यदि आप इसके साथ खेलना चाहते हैं तो यहां एक गॉडबॉल है


1 यह उत्तर उन प्लेटफार्मों पर लागू होता है जहां यह स्थिति नहीं है: उदाहरण के लिए, कुछ का आकार 4 और संरेखण हो सकता है। 2. एक ऐसे मंच पर जहां आकार और संरेखण समान थे, यह प्रश्न संरेखित नहीं किया जाएगा क्योंकि वस्तुओं को ओवरलैप करना। असंभव है, लेकिन मुझे यकीन नहीं है कि अगर कोई ऐसा मंच है।


2
मुझे पूरा यकीन है कि यह यूबी है, लेकिन मैं एक भाषा वकील को अध्याय और कविता प्रदान करने दूंगा।
बमर

मुझे लगता है कि पुराने क्रे वेक्टर सिस्टम पर सी संकलक ने संरेखण और आकार को एक ही होने के लिए मजबूर किया, एक ILP64 मॉडल और मजबूर 64-बिट संरेखण (पते 64-बिट शब्द हैं - कोई बाइट संबोधित नहीं)। बेशक इससे बहुत सी अन्य समस्याएं उत्पन्न हुईं ....
जॉन डी मैकक्लिन

जवाबों:


15

मूल रूप से यह मानक में सभी ग्रे क्षेत्र है; सख्त अलियासिंग नियम बुनियादी मामलों को निर्दिष्ट करता है और विवरण भरने के लिए पाठक (और संकलक विक्रेताओं) को छोड़ देता है।

एक बेहतर नियम लिखने का प्रयास किया गया है, लेकिन अभी तक वे किसी भी मानक पाठ के परिणामस्वरूप नहीं हुए हैं और मुझे यकीन नहीं है कि C2x के लिए इस की स्थिति क्या है।

जैसा कि आपके पिछले प्रश्न के मेरे उत्तर में उल्लेख किया गया है, सबसे आम व्याख्या यह है कि p->qसाधन (*p).qऔर प्रभावी प्रकार सभी पर लागू होता है *p, भले ही हम तब आवेदन करने के लिए जाते हैं .q

इस व्याख्या के तहत, printf("o1.a=%d\n", o1->a);अपरिभाषित व्यवहार का कारण होगा , क्योंकि प्रभावी प्रकार का स्थान *o1नहीं है s(क्योंकि इसका कुछ भाग अधिलेखित किया गया है)।

इस व्याख्या के औचित्य को एक समारोह में देखा जा सकता है:

void f(s* s1, s* s2)
{
    s2->a = 5;
    s1->b = 6;
    printf("%d\n", s2->a);
}

इस व्याख्या के साथ अंतिम पंक्ति को अनुकूलित किया जा सकता है puts("5");, लेकिन इसके बिना, संकलक को यह विचार करना होगा कि फ़ंक्शन कॉल हो सकता है f(o1, o2);और इसलिए उन सभी लाभों को खो दें जो कि सख्त अलियासिंग नियम द्वारा प्रदान किए गए हैं।

एक समान तर्क दो असंबंधित संरचनात्मक प्रकारों पर लागू होता है जो दोनों intअलग-अलग ऑफसेट में एक सदस्य होने के लिए होते हैं ।


1
साथ f(s* s1, s* s2), बिना restrict, संकलक मान नहीं सकता है s1और s2अलग-अलग संकेत हैं। मुझे लगता है , फिर से बिना restrict, यह भी नहीं मान सकते हैं कि वे आंशिक रूप से ओवरलैप नहीं करते हैं। IAC, मैं यह नहीं देखता कि ओपी की चिंता अच्छी तरह से f()सादृश्य द्वारा Demo'd है । गुड लक अनारकली। पहले हाफ के लिए यु.वी.
चक्स -

@ chux-ReinstateMonica बिना किसी रोक-टोक के s1 == s2अनुमति दी जाएगी, लेकिन आंशिक ओवरलैप नहीं। (मेरे कोड उदाहरण में अनुकूलन अभी भी किया जा सकता है s1 == s2)
एमएम

@ chux-ReinstateMonica आप केवल संरचना के intबजाय (और एक प्रणाली _Alignof(int) < sizeof(int)) के साथ एक ही मुद्दे पर विचार कर सकते हैं ।
एमएम

3
C2x के लिए प्रभावी प्रकार के विषय में इस तरह के प्रश्न की स्थिति बहुत खुली है और अभी भी अध्ययन समूह में बहस के अधीन है। की समतुल्यता का दावा के साथ सावधान हालांकि बनें p->qऔर (*p).q। जैसा कि आप बताते हैं, यह प्रकार के अंतर्विरोध के लिए सही हो सकता है, लेकिन परिचालन दृष्टिकोण से यह सच नहीं है। समान संरचना के लिए समवर्ती अभिगम के लिए यह महत्वपूर्ण है कि किसी सदस्य की पहुंच किसी अन्य सदस्य की पहुंच से न हो।
जेन्स गुस्तेद

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