2017-03-07 3 views
1

Wenn Klasse B über einen Konstruktor verfügt, der eine Referenz auf ein Objekt der Klasse A akzeptiert, speichert diese Referenz und wird mit einem temporären dieser Klasse aufgerufen, die Referenz scheint ungültig zu werden, nachdem der Konstruktor beendet wurde (siehe example run).Zugriff auf freigegebene unbenannte temporäre ermitteln

  • g++ -Wall -Wextra -pedantic
  • clang++ -Wall -Wextra -pedantic
  • cppcheck
  • clang-tidy
  • integrierte Kontrollen CLION die

Ich glaube, ich verstehe: Doch keine der statischen Code-Analyse-Tool habe ich versucht, diesen Zustand erkannt dass das Verhalten des Compilers übereinstimmt s zum Standard. Wie erkennt man solchen Code in einer vorhandenen Codebasis? Welche Programmierkonventionen können helfen, solche schwer zu fangenden Fehler zu vermeiden?

Vollständiger Beispielcode und annotierte Ausgabe zur Vollständigkeit.

#include <iostream> 

class A { 
public: 
    explicit A(int i) : i_(i) { std::cerr << this << " A\n"; } 
    ~A() { std::cerr << this << " ~A\n"; } 

    void do_() const { std::cerr << this << " " << i_ << "\n"; } 

private: 
    int i_; 
}; 

class B { 
public: 
    explicit B(const A& a) : a_(a) { std::cerr << this << " B\n"; } 
    ~B() { std::cerr << this << " ~B\n"; } 
    void do_() const { std::cerr << this << " "; a_.do_(); } 

    const A& a_; 
}; 

int main(int, char**) { 
    B b(A(42)); 
    int i = 0; 
    b.do_(); 
    std::cerr << i << " main\n"; 
} 

Ausgang:

# Construction of b 
0xffa66138 A 
0xffa66134 B 
0xffa66138 ~A 
# Calling b.do_() 
0xffa66134 0xffa66138 42 
# Printing i in main() 
0 main 
# End of main() 
0xffa66134 ~B 
+2

Suchen Sie einfach nach Klassen, die Referenzen als Elementvariablen enthalten - das ist fast immer nicht das, was Sie wollen. Ein Regex sollte die meisten Fälle finden können. –

+1

Ich würde nur Referenzmitglieder in den Klassen verbieten. – NathanOliver

+0

Selbst wenn Sie Provisorien verbieten/verhindern, würden Sie immer noch Probleme haben, wenn ein Objekt von 'B' das referenzierte Objekt von' A' (freie Referenz) überlebt? – UnholySheep

Antwort

2

Sie können mit gelöschten Konstruktor

class B { 
public: 
    explicit B(const A& a) : a_(a) { std::cerr << this << " B\n"; } 
    B(A&&) = delete; 
// ... 
}; 

Ein Weg zu garantieren, dass Lebensdauer von A länger als B wäre zu nehmen shared_ptr vorübergehend verbieten.

Verwandte Themen