2016-08-04 7 views
6

işaretçi üyesi atamak UsesTheCallable yapıcısına m_callable üyesini argümanın adresine atayın; bu, yapıcının tne ucunda kapsam dışı kalmalı ve böylece UsesTheCallable::call() numaralı telefonu aradığımda, artık mevcut olmayan bir nesne üzerinde çalışıyorum.Geçiş çağrılabilir nesne, aşağıdaki Biz esas yapan bir taşeron gelen kodu almış

yüzden bu ana yöntemle denedim:

int main(int, char**) 
{ 
    UsesTheCallable<Callable>* u = NULL; 

    { 
     Callable c; 
     u = new UsesTheCallable<Callable>(c); 
    } 

    u->call(); 

    delete u; 

    return 0; 
} 

Ben Callable nesne ben UsesTheCallable::call() aramadan önce kapsam dışına gider emin olun, bu yüzden bellek işlevini çağırarak olması gerektiğini ı don Aslında bu noktada var. Ancak kod çalışıyor ve Valgrind, Callable sınıfına bazı üye verileri eklese ve operator() işlevinin bu üye verilerinde hareket etmesini sağlasa bile bellek hataları bildirmiyor.

Bu kodun tanımlanmamış bir davranış olduğunu düzelttim mi? Callable'un üye verilerine sahip olup olmadığına (ör. Özel bir int değişken veya bir şey) bağlı olarak bu kodun "tanımlı" kısmında bir fark var mı?

+0

Sadece bir şey "çalışıyor", gördüğünüz davranış tanımsız olduğu anlamına gelmez. Şimdi "çalışabilir" ve bazı rastgele alakasız kodlar ekliyor ve çalışmayı durduruyor. – iheanyi

+0

@iheanyi: OP, bunu biliyor gibi görünüyor ya da kodun UB'ye sahip olup olmadığını sormuyorlardı. –

+0

@iheanyi Bunun farkındayım. Sadece alt yüklenicimize ne yaptıklarını bilmediklerini söyleyen _sure_ undefined yapmak istedim – villapx

cevap

7

Evet, bu tanımlanmamış bir davranış. Kurucu callable kapanış ayracı yıkıldıktan sonra ve sarkan bir işaretçiniz var.

Yan etkileri görmemenizin nedeni, örneği kapsam dışında kaldığında gerçekten kullanmamanızdır. Fonksiyon çağrısı operatörü vatansız, bu yüzden artık sahip olmadığı belleğe erişmeye çalışmıyor.Biz

class Callable 
{ 
    int foo; 
public: 
    Callable (int foo = 20) : foo(foo) {} 
    void operator()(int x) 
    { 
     printf("x = %d\n", x*foo); 
    } 
}; 

gibi çağrılabilir bazı devlet ekleyin ve sonra biz

int main() 
{ 
    UsesTheCallable<Callable>* u = NULL; 
    { 
     Callable c(50); 
     u = new UsesTheCallable<Callable>(c); 
    } 
    u->call(); 
    delete u; 
    return 0; 
} 

kullanırsanız

Sonra bu bad behavior görebiliyordu. Bu çalışmada, doğru olmayan x = 772773112 çıktı.

+1

Yine sen! ....;) –

+1

Birimiz düşündüğümüz diğer tarafa bakıyor;) – NathanOliver

+0

"Kötü davranış göreceksiniz." Şart değil. Bu hala yazdırılabilir 50. – Barry

7
m_callable = &callable; 

Am Bu kod tanımsız davranış olduğunu düzeltmek?

Evet, bu saçmalık!

Ama kod

Evet, o UB & hellip neler olur? Çalışır;

ve Valgrind hafıza hatalarını

& hellip raporları, siz ameliyat ediyoruz bellek hala sürecine "aittir" özellikle. Valgrind'in burada tespit edilmesi için hiçbir şey yok; C++ kapsamlarını doğrulamaz, yalnızca "fiziksel" & hançer; bellek erişir. Ve program çökmez çünkü hiçbir şey henüz c tarafından ele geçirilen hafızayı karıştırmak için çok fazla şansı yoktu.

& dagger; "Fiziksel", C++ 'nın soyut kavramları yerine, işletim sistemine ve onun bellek yönetimine atıfta bulunduğum anlamda. Aslında sanal bellek ya da her neyse.

İlgili konular