Clang 3.9'a yönelik sarkan atıfları algılar, geçici olarak kullanılan bellekleri yeniden kullanır. (my_optional
bunu göstermek için sadece basit bir örnektir) Yukarıda gibi kod şey tonlarcaGeçici
template <class T>
class my_optional
{
public:
bool has{ false };
T value;
const T& get_or_default(const T& def)
{
return has ? value : def;
}
};
void use(const std::string& s)
{
// ...
}
int main()
{
my_optional<std::string> m;
// ...
const std::string& s = m.get_or_default("default value");
use(s); // s is dangling if default returned
}
:
Bu kod UB (basitleştirilmiş kod) 'dir.
UB'den dolayı tüm clang derleyici 3.9'dan beri bu belleği yeniden kullanmaya başlar ve bu yasal bir davranıştır.
Sorun şu ki: ,'u derleme zamanında ya da çalışma zamanında sanitizer gibi bir şeyle ilgili sarkan referansları nasıl algılar? Clang dezenfektanı onları tespit edemez.
Upd. Lütfen cevaplamayın: "std::optional
kullanın". Dikkatle okuyun: soru bu konuda DEĞİLDİR.
Upd2. Lütfen cevaplamayın: "kod tasarımınız kötü". Dikkatle okuyun: soru kod tasarımı ile ilgili DEĞİLDİR. get_or_default
verilen argüman gerçek rvalue ise bunun yerine seçilecek,
const T& get_or_default(T&& rvalue) = delete;
, bu nedenle derleme başarısız olur:
@Someprogrammerdude Teşekkür ederim, biliyorum. Asıl nokta şudur: sabit değil, fakat std :: string ("varsayılan değer") örtülü olarak yapılmış, bu geçici bir durumdur ve o satırdan sonra ölür. Yani sıradaki satır sarkıyor. – vladon
Numara. Dize * geçici * nesne _dies_ satırın sonunda. Referans, 'use (s)' satırında sarkıyor. – vladon
@Someprogrammerdude "bir işlev çağrısındaki bir referans parametresine geçici bir sınırlama, bu işlev çağrısını içeren tam ifadenin sonuna kadar var: işlev, tam ifadeyi aşan bir başvuru döndürürse," http://en.cppreference.com/w/cpp/language/reference_initialization#Lifetime_of_a_temporary – vladon