Bugün sadece zaman zaman belirli platformlarda meydana gelen iğrenç bir hatanın nedenini bulduk. Kaynatılmış, kodumuz şöyle görünüyordu:
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);
}
}
}
Sorun bu basitleştirilmiş durumda açık görünebilir: basmaya başlamadan önce harita girişini kaldıran B
anahtara anahtar A
gönderir. (Bizim durumumuzda, basılmadı, ancak daha karmaşık bir şekilde kullanıldı) Bu elbette tanımsız bir davranış, çünkü key
çağrıdan sonra sarkan bir referans erase
.
Bunu düzeltmek önemsizdi - biz sadece parametre türünü olarak const string&
değiştirdik string
. Soru şu: En başta bu böceği nasıl önleyebilirdik? Her iki fonksiyon da doğru olanı yapmış görünüyor:
A
key
imha etmek üzere olduğu şeyi ifade ettiğini bilmenin hiçbir yolu yoktur .B
iletmeden önce bir kopyasını almış olabilirdiA
, ancak parametreleri değere mi yoksa referansa göre mi almayacağına karar vermek Callee'nin işi değil mi?
Takip edemediğimiz bazı kurallar var mı?