1. ホーム
  2. c++

[解決済み] 何かを「投げる」とき、それはメモリーのどこに格納されるのですか?

2023-07-10 12:04:02

質問

私は、あるものが throw n が発生すると、それが捕捉された時点までスタックが「巻き戻され」、各関数コンテキストでスタック上のクラス インスタンスのデストラクタが実行されます (これがデストラクタから例外をスローしてはいけない理由です - 2 番目の例外をスローすることになります)...が、私はこれが発生している間にスローしたオブジェクトはメモリ内のどこに格納されるのかと疑問に思っています。

実装に依存しているのでしょうか?もしそうなら、ほとんどの一般的なコンパイラーによって使用される特定の方法があるのでしょうか?

どのように解決するのですか?

はい、答えはコンパイラに依存します。

私のコンパイラーで簡単な実験をしてみました ( g++ 4.4.3 ) のランタイムライブラリは、最初に malloc のメモリを確保しようとし、それがうまくいかない場合は、データ セグメントに存在するプロセス全体の "emergency buffer" 内のスペースを確保しようとします。それがうまくいかなかった場合、ランタイムライブラリは 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));
}

このスキームがどの程度典型的なものなのかはわからない。