我有這個函式,我試圖回傳一個 const char*,但是當我嘗試輸出回傳的值時,我得到垃圾值;
virtual const char* what() const noexcept
{
std::stringstream s;
if(m_id > -1)
s << m_message << " with id " << m_id << " does not exist";
else
s << m_message << " with name " << m_name << " does not exist";
//until now it works fine
std::string tmp = s.str();
const char* temp = tmp.c_str();
return temp; //after I execute this command, the value is deleted.
}
當我嘗試列印時:
catch (std::exception& e)
{
std::cout << e.what() << std::endl;
}
我明白了(每次都不一樣..):
▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌╢P??▌'
我究竟做錯了什么?
uj5u.com熱心網友回復:
char您正在回傳指向函式退出時被破壞的本地物件的內部資料的std::string指標,因此回傳的指標懸空,指向無效記憶體。之后嘗試訪問資料是未定義的行為。
通常,您有兩種選擇來解決這個問題:
回傳 a
std::string而不是char*指標。動態分配
char資料,然后讓呼叫者在使用完后釋放它。
但是,在這種情況下,您將覆寫該std::exception::what()方法,因此這些選項都不可行。您必須做的是將char資料存盤在std::string派生類的成員中,然后您可以回傳char*指向其資料的指標,例如:
private:
std::string m_what;
myException::myException(...)
{
...
std::stringstream s;
if (m_id > -1)
s << m_message << " with id " << m_id << " does not exist";
else
s << m_message << " with name " << m_name << " does not exist";
m_what = s.str();
}
virtual const char* what() const noexcept
{
return m_what.c_str();
}
std::runtime_error如果您從而不是直接派生例外類std::exception,這已經為您處理好了。std::runtime_error在其建構式中接受一個字串,并覆寫what()以回傳該字串的資料。
uj5u.com熱心網友回復:
問題是該tmp函式是本地的,what并且您正在回傳指向該本地內部陣列的指標。這是一個問題,因為一旦函式退出,本地將被銷毀。也就是說,您回傳的指標是一個懸空指標。使用那個懸空指標(你在寫的時候做std::cout << e.what() << std::endl;的)是未定義的行為。
未定義的行為意味著任何事情1都可能發生,包括但不限于給出預期輸出的程式。但永遠不要依賴(或基于)具有未定義行為的程式的輸出。
所以你看到的輸出(也許看到)是未定義行為的結果。正如我所說,不要依賴具有 UB 的程式的輸出。該程式可能會崩潰。
因此,使程式正確的第一步是洗掉 UB。只有這樣,您才能開始推理程式的輸出。
1有關未定義行為的更技術上準確的定義,請參見此處提到:對程式的行為沒有限制。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/443087.html
上一篇:從二維陣列調整串列大小
