आज हमें एक बुरा बग का कारण पता चला जो केवल कुछ प्लेटफार्मों पर रुक-रुक कर हुआ। उबला हुआ, हमारे कोड इस तरह देखा:
class Foo {
map<string,string> m;
void A(const string& key) {
m.erase(key);
cout << "Erased: " << key; // oops
}
void B() {
while (!m.empty()) {
auto toDelete = m.begin();
A(toDelete->first);
}
}
}
इस सरलीकृत मामले में समस्या स्पष्ट लग सकती है: B
कुंजी का संदर्भ A
देता है, जो इसे प्रिंट करने का प्रयास करने से पहले मानचित्र प्रविष्टि को हटा देता है। (हमारे मामले में, यह मुद्रित नहीं किया गया था, लेकिन अधिक जटिल तरीके से उपयोग किया गया) यह निश्चित रूप से अपरिभाषित व्यवहार है, क्योंकि key
कॉल के बाद एक झूलने वाला संदर्भ है erase
।
इस फिक्सिंग तुच्छ था - हम सिर्फ से पैरामीटर प्रकार बदल const string&
करने के लिए string
। सवाल यह है कि हम पहली बार में इस बग से कैसे बच सकते थे? ऐसा लगता है कि दोनों कार्यों ने सही काम किया:
A
यह जानने का कोई तरीका नहीं है कि यह उसkey
चीज़ को संदर्भित करता है जो इसे नष्ट करने वाली है।B
इसे पास करने से पहले एक प्रति बना सकता थाA
, लेकिन क्या यह मानने या संदर्भ द्वारा मानदंड लेने का फैसला करना कैली का काम नहीं है?
क्या कोई नियम है जिसका हम पालन करने में विफल रहे हैं?