2016-04-22 21 views
1

Ich habe ein sehr seltsames Verhalten, das ich nicht verstehen kann.Merkwürdiges Verhalten von std :: make_shared

Dieser Test bestanden:

CipString str = *std::make_shared<CipString>("Bye!").get(); 
EXPECT_EQ(static_cast<std::string>(str), "Bye!"); 

Aber das ist nicht:

CipString *str = std::make_shared<CipString>("Bye!").get(); 
EXPECT_EQ(static_cast<std::string>(*str), "Bye!"); 

ich einen Fehler bekam:

Expected: static_cast(*str)

Which is: "p\x15\x97\x1"

To be equal to: "Bye!"

Die CipString Code:

class CipString{ 
    public: 

    CipString(const std::string& str) { 
    length = str.size(); 
    string.reset(new uint8_t[length]); 
    std::copy(str.begin(), str.end(), string.get()); 
    } 

    operator std::string() const { 
    std::string str("", length); 
    std::copy(string.get(), string.get() + length, str.begin()); 
    return str; 
    } 

    uint16_t length; /**< Length of the String (16 bit value) */ 
    std::shared_ptr<uint8_t> string; /**< Pointer to the string data */ 
}; 
+4

undefiniertes Verhalten, da Sie baumelnden Zeiger überall haben. –

Antwort

8

Diese Zeile:

CipString *str = std::make_shared<CipString>("Bye!").get(); 

schafft eine shared_ptr, die kurz nach dem ; zerstört wird. str ist ein Dangling-Zeiger danach, und Ihr Test ruft ein undefiniertes Verhalten auf, indem auf freigegebenen Speicher zugegriffen wird.

Sie behaupten grundsätzlich gegen Müll Speicher.

0
CipString str = *std::make_shared<CipString>("Bye!").get(); 
EXPECT_EQ(static_cast<std::string>(str), "Bye!"); 

zersetzt sich zu:

1) Ruf

3) konstruieren, um das CipString mit dem Zeiger auf den Basiswert Shared_ptr

2) erhalten, um die Adresse des zugrunde liegenden Objekts zurückzukehren make_shared Objekt

4) zerstören shared_ptr

die 'fein'

Dies Dies zersetzt zu: a Shared_ptr

2) erhalten, um die Adresse des zugrunde liegenden Objekts

3) Erstellen eines temporären CipString konstruieren

CipString *str = std::make_shared<CipString>("Bye!").get(); 

1) von ihm und speichern Sie die Adresse in str

4) zerstören die shared_ptr

5) zerstören das temporäre CipString (die str at)

was bedeutet, zeigt, dass dies:

EXPECT_EQ(static_cast<std::string>(*str), "Bye!"); 

0

undefiniertes Verhalten werden Sie können dieses umschreiben:

CipString str = *std::make_shared<CipString>("Bye!").get(); 
EXPECT_EQ(static_cast<std::string>(str), "Bye!"); 

wie:

CipString str; 
{ 
    auto sp = std::make_shared<CipString>("Bye!"); 
    str = *sp.get(); // here a copy is made (in original code copy initialization) 
    // here sp will get destroyed 
} 
// here str contains correct "Bye!" value 

Und das hat kein undefiniertes Verhalten.Auf der anderen Seite dieses Code:

CipString *str = std::make_shared<CipString>("Bye!").get(); 

würde als neu geschrieben werden:

CipString *str; 
{ 
    auto sp = std::make_shared<CipString>("Bye!"); 
    str = sp.get(); // here a pointer is assigned to str, no copy is done as above 
    // here sp will get destroyed, and also pointer to 
    // which str points will be a dangling pointer 
} 
// here str should not be used - as it is UB 
Verwandte Themen