どうして `e.what()`「悪い割り当て」を印刷しますか?
-
26-10-2019 - |
質問
new
での表現 try
ブロックスローa bad_alloc
私のコンピューターの例外。
Catch句は、参照ではなく、値によって例外オブジェクトを受信することに注意してください。どうして e.what()
プリント "bad allocation"
?スライスされると思いました。
#include <iostream>
int main()
{
try
{
int* p = new int[0x1F000000];
}
catch(std::exception e)
{
std::cout << e.what() << std::endl;
}
}
解決
Visual Studio(dinkumware?)はの実装を使用します std::exception
メッセージ用の内部ストレージ†が含まれています。 (文字列を受け入れる標準以外のコンストラクターを備えています。)
このため、エラーメッセージを取得するために実際に仮想ディスパッチは必要ありません。スライシングは存続します。
より正統派の実装は、派生オブジェクトがスライスされたため、実際に一般的な例外メッセージを印刷します。 (事実上、MSが作成しました std::exception
と std::runtime_error
同等。の返品値からこれには何の問題もありません std::exception::what
実装が定義されていますが、結果を説明しています。)
†ここの内部ストレージはゆるく使用されます。内部はありません バッファ, 、しかし、それは const char*
そしてa bool
. 。 const char*
メッセージを指します(の返品値 what()
)、 そしてその bool
バッファを削除するかどうかを決定するフラグです。
こんな感じです:
class msvc_exception // for exposition
{
public:
msvc_exception(const char* msg) :
mMsg(msg),
mDoDelete(false)
{}
msvc_exception(const std::string& msg) :
mMsg(copy_string(msg)),
mDoDelete(true)
{}
virtual ~msvc_exception()
{
if (mDoDelete)
delete [] mMsg;
}
virtual const char* what() const throw()
{
return mMsg ? mMsg : "unknown";
}
private:
const char* copy_string(const std::string& str)
{
const char* result = new char[str.size() + 1];
std::copy(str.begin(), str.end(), result);
result[str.size()] = 0; // null-terminate
return result;
}
};
あなたは今それを見る bad_alloc
このような作品:
class msvc_bad_alloc : // for exposition
public msvc_exception
{
public:
msvc_bad_alloc() :
msvc_exception("bad_alloc") // note: a static string, no dynamic storage
{}
};
メッセージが基本クラスに「存在する」ため、スライスはメッセージに影響しません。
GCCやLLVMのような他のコンパイラは、もう少し簡単に実装してください。
class orthodox_exception
{
public:
orthodox_exception(){}
virtual ~orthodox_exception() {}
virtual const char* what() const throw()
{
return "orthodox_exception";
}
};
class orthodox_bad_alloc :
public orthodox_exception
{
public:
const char* what() const throw()
{
return "orthodox_bad_alloc";
}
};
ここで、スライスはあなたの結果に影響します。 (それは結局のところ:常に参照してキャッチします。)