क्या किसी वस्तु के सदस्य फ़ंक्शन को फिर से शुरू करना यूबी है जिसका जीवनकाल समाप्त हो गया है?


9

यह प्रश्न इस टिप्पणी से उपजा है: C ++ 20 कोराउटाइन के लिए लैम्बडा आजीवन स्पष्टीकरण

इस उदाहरण के बारे में:

auto foo() -> folly::coro::Task<int> {
    auto task = []() -> folly::coro::Task<int> {
        co_return 1;
    }();
    return task;
}

तो सवाल यह है कि क्या कोरटाइन को अंजाम देकर लौटे foo यूबी का परिणाम होगा।

"कॉलिंग" एक सदस्य फ़ंक्शन (ऑब्जेक्ट का जीवनकाल समाप्त होने के बाद) यूबी है: http://eel.is/c++draft/basic.life#6.2

... कोई भी पॉइंटर जो उस स्टोरेज लोकेशन के पते को दर्शाता है, जहाँ ऑब्जेक्ट होगा या स्थित था, का उपयोग किया जा सकता है लेकिन केवल सीमित तरीकों से। [...] कार्यक्रम में अपरिभाषित व्यवहार है यदि:

[...]

- सूचक का उपयोग गैर-स्थैतिक डेटा सदस्य तक पहुंचने के लिए किया जाता है या ऑब्जेक्ट के गैर-स्थिर सदस्य फ़ंक्शन को कॉल करने के लिए , या

हालाँकि, इस उदाहरण में:

  • ()लैम्ब्डा के ऑपरेटर को कहा जाता है जबकि लैम्बडा का जीवनकाल अभी भी मान्य है
  • इसके बाद उसे निलंबित कर दिया गया,
  • तब मेमना नष्ट हो जाता है,
  • और फिर सदस्य फ़ंक्शन (ऑपरेटर ()) को कुछ बिंदु पर फिर से शुरू किया जाता है।

क्या इस बहाली को अपरिभाषित व्यवहार माना जाता है?


2
हो सकता है कि निम्नलिखित उत्तर प्रासंगिक stackoverflow.com/a/60495359/12345656 है यह बहुत अलग लगता है, लेकिन यह एक सदस्य फ़ंक्शन के बारे में भी है जिसके दौरान thisसूचक अमान्य है। टिप्पणियों में चर्चा पर भी विचार करें।
n314159

जवाबों:


2

[dcl.fct.def.coroutine] p3 :

वादा प्रकार एक coroutine की है std::coroutine_traits<R, P1, ..., Pn>::promise_type, जहां Rसमारोह की वापसी प्रकार है, और P1 ... Pnएक फ़ंक्शन पैरामीटर प्रकार के अनुक्रम, कर रहे हैं निहित वस्तु पैरामीटर के प्रकार से पहले (12.4.1) यदि coroutine एक गैर स्थिर है सदस्य समारोह।

अंतर्निहित ऑब्जेक्ट पैरामीटर आपके उदाहरण में एक कॉन्स्ट रेफरेंस है, और इसलिए क्लोजर ऑब्जेक्ट के नष्ट होने के बाद निष्पादन को फिर से शुरू करने पर यह संदर्भ झूलने लगेगा।

हालाँकि, सदस्य फ़ंक्शन के निष्पादन के दौरान नष्ट होने वाली वस्तुओं के नोट पर, यह वास्तव में प्रति से ठीक है, और मानक के अलावा कोई अन्य इसका मतलब नहीं है [मूल] :

किसी वस्तु का जीवनकाल शुरू होने से पहले लेकिन भंडारण के बाद जिस वस्तु पर कब्जा हो जाएगा उसे आवंटित किया गया है या किसी वस्तु के जीवनकाल के समाप्त होने के बाद और भंडारण से पहले जिस वस्तु पर कब्जा किया गया है उसका पुन: उपयोग या विमोचन किया जाता है, कोई भी सूचक जो पता का प्रतिनिधित्व करता है भंडारण स्थान जहां ऑब्जेक्ट होगा या स्थित था, का उपयोग किया जा सकता है लेकिन केवल सीमित तरीकों से। [...]

void B::mutate() {
  new (this) D2;    // reuses storage --- ends the lifetime of *this
  f();              // undefined behavior
  ... = this;       // OK, this points to valid memory
}

(एनबी: उपरोक्त यूबी इसलिए है क्योंकि निहित thisनहीं है और फिर भी निहित वस्तु पैरामीटर को संदर्भित करता है।)

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


क्या आपका मतलब अंत में "फिर से शुरू और पूरा" है?
डेविस हेरिंग

@DavisHerring नहीं, मेरा मतलब है कि विशेष रूप से "बाहर" समय सीमा के भीतर, जहां यह स्पष्ट नहीं है कि क्या संदर्भ को एक नए संदर्भ आदि को सौंपा जा सकता है, जिसे एक वास्तविक वस्तु की आवश्यकता होगी। तथ्य यह है कि संदर्भ को एक छिपे हुए तरीके से एक्सेस नहीं किया गया है, इसके लिए यूबी नहीं होना महत्वपूर्ण है
कोलंबो

लेकिन यह फिर से शुरू होने तक झूलने के संदर्भ को छोड़ने के लिए पर्याप्त नहीं है; आपको इसे अकेला छोड़ना होगा ( जैसे , मेमने के शरीर में) हमेशा के लिए - अपने जीवनकाल के बाकी समय के लिए, जो पूरा होने तक है। तो शायद यह "निलंबन और समापन" होना चाहिए।
डेविस हेरिंग

@DavisHerring मैंने विशेष रूप से उस अंतराल का उल्लेख किया है, क्योंकि हमारे उदाहरण में हम दूसरे को सुरक्षित होना जानते हैं।
कोलंबो

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