何かがthrow
n の場合、スタックはキャッチされたポイントまで「アンワインド」され、各関数コンテキストのスタック上のクラス インスタンスのデストラクタが実行される (デストラクタから例外をスローしてはいけないのはそのためです。2 つ目の例外をスローすることになる可能性があります) ことは理解していますが、これが起こっている間にスローしたオブジェクトがメモリのどこに保存されるのか疑問に思います。
それは実装に依存しますか? もしそうなら、最も人気のあるコンパイラで使用される特定の方法がありますか?
ベストアンサー1
はい、答えはコンパイラに依存します。
私のコンパイラ ( ) で簡単に実験してみるg++ 4.4.3
と、そのランタイム ライブラリは最初にmalloc
例外のメモリを試行し、それが失敗すると、データ セグメントに存在するプロセス全体の「緊急バッファー」内にスペースを割り当てようとすることがわかります。それがうまくいかない場合は、 を呼び出しますstd::terminate()
。
std::bad_alloc
緊急バッファの主な目的は、プロセスのヒープ領域が不足した後 (その場合、malloc
呼び出しは失敗します) にスローできるようにすることであると思われます。
関連する機能は__cxa_allocate_exception
:
extern "C" void *
__cxxabiv1::__cxa_allocate_exception(std::size_t thrown_size) throw()
{
void *ret;
thrown_size += sizeof (__cxa_refcounted_exception);
ret = malloc (thrown_size);
if (! ret)
{
__gnu_cxx::__scoped_lock sentry(emergency_mutex);
bitmask_type used = emergency_used;
unsigned int which = 0;
if (thrown_size > EMERGENCY_OBJ_SIZE)
goto failed;
while (used & 1)
{
used >>= 1;
if (++which >= EMERGENCY_OBJ_COUNT)
goto failed;
}
emergency_used |= (bitmask_type)1 << which;
ret = &emergency_buffer[which][0];
failed:;
if (!ret)
std::terminate ();
}
// We have an uncaught exception as soon as we allocate memory. This
// yields uncaught_exception() true during the copy-constructor that
// initializes the exception object. See Issue 475.
__cxa_eh_globals *globals = __cxa_get_globals ();
globals->uncaughtExceptions += 1;
memset (ret, 0, sizeof (__cxa_refcounted_exception));
return (void *)((char *)ret + sizeof (__cxa_refcounted_exception));
}
この計画がどの程度典型的なものなのかは分かりません。