c++ - अनपेक्षित परिणाम जब सी++ स्टोर तत्व std:: वेक्टर में फ़ंक्शन के वापसी मूल्य से




gcc vector (2)

यदि आप "इटरेटर अमान्यता" के तहत documentation जांच करते हैं, तो आप देखेंगे कि push_back() क्षमता को बदलने पर प्रत्येक पुनरावर्तक को अमान्य कर सकता है, क्योंकि इसे स्मृति को पुन: आवंटित करना होगा। याद रखें कि, एक std::vector , एक सूचक एक मान्य इटरेटर भी है। चूंकि push_back() पुन: आवंटित हो सकता है या नहीं, और आपके पास यह जानने का कोई तरीका नहीं है कि यह क्या होगा, व्यवहार अपरिभाषित है।

जब फ़ंक्शन में पुनर्वितरण शामिल होता है, तो मैंने पाया कि कुछ कंपाइलर फ़ंक्शन कॉल से पहले पते को सहेज सकते हैं। यह अमान्य पते में संग्रहीत वापसी मूल्य का नेतृत्व करता है।

उपरोक्त वर्णन में व्यवहार को समझाने के लिए एक उदाहरण है।

#include <stdio.h>
#include <vector> 
using namespace std;

vector<int> A; 
int func() { 
    A.push_back(3);
    A.push_back(4);
    return 5; 
} 
int main() { 
    A.reserve(2);
    A.push_back(0);
    A.push_back(1);
    A[1] = func();
    printf("%d\n", A[1]);
    return 0;
}

कुछ सामान्य सी ++ कंपाइलर हैं, और परीक्षण परिणाम निम्नानुसार हैं।

  • जीसीसी (जीएनयू कंपाइलर संग्रह): रनटाइम त्रुटि या आउटपुट 1
  • क्लैंग: आउटपुट 5
  • वीसी ++: आउटपुट 5

क्या यह अनिर्धारित व्यवहार है?


व्यवहार C ++ 17 से पहले सभी C ++ संस्करणों में अपरिभाषित है। सरल कारण यह है कि असाइनमेंट ऑपरेटर के दोनों पक्षों का मूल्यांकन किसी भी क्रम में किया जा सकता है:

  • मान लें कि A[1] का मूल्यांकन पहले किया जाता है, आप उस बिंदु पर A के दूसरे तत्व को int& संदर्भित करते हैं।
  • फिर, func() का मूल्यांकन किया जाता है, जो वेक्टर के लिए भंडारण को पुन: आवंटित कर सकता है, जो पहले पुनर्प्राप्त int& एक लटकती संदर्भ को छोड़ देता है।
  • अंत में, असाइनमेंट किया जाता है, आवंटित स्टोरेज को लिखना। चूंकि मानक आवंटक कैश मेमोरी करते हैं, इसलिए ओएस अक्सर इस त्रुटि को नहीं पकड़ पाएगा।

केवल सी ++ 17 में, असाइनमेंट के लिए विशेष नियम 20 बनाया गया था:

प्रत्येक सरल असाइनमेंट अभिव्यक्ति E1 = E2 और प्रत्येक यौगिक असाइनमेंट अभिव्यक्ति E1 @ = E2 में, प्रत्येक मान गणना और ई 2 के दुष्प्रभाव को प्रत्येक मान गणना और ई 1 के दुष्प्रभाव से पहले अनुक्रमित किया जाता है

सी ++ 17 के साथ, A[1] का मूल्यांकन func() कॉल के बाद किया जाना चाहिए, जो तब परिभाषित, भरोसेमंद व्यवहार प्रदान करता है।





compiler-bug