何かがthrow
nの場合、スタックはキャッチされるまで「巻き戻され」、各関数コンテキストのスタック上のクラスインスタンスのデストラクタが実行されることを理解しています(そのため、デストラクタから例外をスローしないでください)。 -あなたは2番目のものを投げることになるかもしれません)...しかし、これが起こっている間、私が投げたオブジェクトはメモリのどこに保存されているのだろうか?
実装に依存しますか?もしそうなら、最も人気のあるコンパイラで使用される特定の方法はありますか?
何かがthrow
nの場合、スタックはキャッチされるまで「巻き戻され」、各関数コンテキストのスタック上のクラスインスタンスのデストラクタが実行されることを理解しています(そのため、デストラクタから例外をスローしないでください)。 -あなたは2番目のものを投げることになるかもしれません)...しかし、これが起こっている間、私が投げたオブジェクトはメモリのどこに保存されているのだろうか?
実装に依存しますか?もしそうなら、最も人気のあるコンパイラで使用される特定の方法はありますか?
raise
)、それを破棄します。ヒープ割り当ての問題は、例外を割り当てる試みが失敗した場合、どうしますか?中止する必要があります(スペース不足のためにスタックに置くことが「失敗」した場合のスタックオーバーフローの場合と同じように)。Javaとは異なり、実装では代わりに別の例外をスローすることはできません。
回答:
はい、答えはコンパイラに依存します。
私のコンパイラ(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));
}
このスキームがどれほど典型的かはわかりません。
malloc
呼び出しは失敗します」通常、ただし必ずしもそうとは限りません。
このページから:
例外がスローされるためにストレージが必要です。このストレージは、ハンドラーによって使用されるため、スタックが巻き戻されている間も存続する必要があり、スレッドセーフである必要があります。したがって、例外オブジェクトストレージは通常、ヒープに割り当てられますが、 実装では、メモリ不足の条件下でbad_alloc例外のスローをサポートする緊急バッファが提供される場合があります。
現在、これはItanium ABIのみであり、GCC、Clang、およびMSVCに固有の詳細を探しています。ただし、標準では何も指定されておらず、これは例外ストレージを実装するための明白な方法のようです。
これがあなたの質問に答えるかどうかはわかりませんが、これ(C ++コンパイラが例外処理を実装する方法)は、例外処理に関する優れた記事です。私はそれを強くお勧めします(:
短い答えで申し訳ありませんが、記事のすべての情報は素晴らしいです、私はここでいくつかの情報を選んで投稿することはできません。
excpt_info
そのページで検索すると、MSVCがどのようにそれを行うかについての情報が得られます。
まあ、それは巻き戻されるのでスタックに置くことはできませんし、ヒープに置くこともできませんstd::bad_alloc
。それはシステムがスローできない可能性があることを意味するからです。それ以外は、完全に実装次第です。実装は指定されていません(文書化する必要があります)が、指定されていません。(実装は、メモリがなくなった場合でも限られた数の例外を許可する何らかの緊急バックアップがある限り、ほとんどの場合ヒープを使用できます。)
std::bad_alloc
ます。これは、実装がヒープを体系的に使用できないことを意味します。標準では許可されていません。私は自分の主張を標準に基づいています。