簡體   English   中英

std :: make_shared的奇怪行為

[英]Strange behaviour of std::make_shared

我有一個非常奇怪的行為,我無法理解。

該測試通過:

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

但這不是:

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

我收到一個錯誤:

預期:static_cast(* str)

這是:“ p \\ x15 \\ x97 \\ x1”

等於:“再見!”

CipString的代碼:

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 */
};

這行:

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

創建一個shared_ptr,它在;之后被銷毀; 之后, str是一個懸空指針,您的測試通過訪問釋放的內存來調用未定義的行為。

您基本上是在聲明垃圾內存。

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

分解為:

1)調用make_shared返回shared_ptr

2)獲取底層對象的地址

3)使用指向基礎對象的指針構造CipString

4)銷毀shared_ptr

很好

這分解為:

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

1)構造一個shared_ptr

2)獲取底層對象的地址

3)從中創建一個臨時CipString並將地址存儲在str中

4)銷毀shared_ptr

5)銷毀臨時CipString(str指向的)

這意味着:

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

變成不確定的行為

您可以重寫以下內容:

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

如:

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

這沒有未定義的行為。 另一方面,此代碼:

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

將被重寫為:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM