首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当我“抛出”一些东西时,它存储在内存中的什么地方?

当我“抛出”一些东西时,它存储在内存中的什么地方?
EN

Stack Overflow用户
提问于 2011-07-07 22:04:14
回答 3查看 2.5K关注 0票数 83

我知道当某件事是thrown时,堆栈被“展开”到它被捕获的程度,每个函数上下文中堆栈上的类实例的析构函数都会运行(这就是为什么你不应该从析构函数中抛出异常--你可能会抛出第二个异常)...but我想知道当这种情况发生时,我抛出的对象在内存中存储在哪里?

它依赖于实现吗?如果是这样的话,有没有被大多数流行的编译器使用的特殊方法?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-07-07 22:14:29

是的,答案取决于编译器。

使用我的编译器(g++ 4.4.3)进行的快速实验显示,它的运行时库首先尝试为异常分配malloc内存,如果失败,则尝试在驻留在数据段上的进程范围内的“紧急缓冲区”中分配空间。如果这不起作用,它将调用std::terminate()

紧急缓冲区的主要用途似乎是能够在进程用完堆空间后抛出std::bad_alloc (在这种情况下,malloc调用将失败)。

相关函数为__cxa_allocate_exception

代码语言:javascript
复制
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));
}

我不知道这个计划有多典型。

票数 53
EN

Stack Overflow用户

发布于 2011-07-07 22:19:46

C++标准通常指定语言的行为方式,但不指定编译器应该如何实现该行为。我认为这个问题就属于这一类。实现这样的东西的最佳方式取决于机器的具体情况--有些处理器有很多通用寄存器,有些处理器只有很少的寄存器。甚至可以使用专门的异常寄存器来构建处理器,在这种情况下,编译器应该可以自由地利用该特性。

票数 0
EN

Stack Overflow用户

发布于 2011-07-07 22:22:53

嗯,它不能在堆栈上,因为它将被展开,它不能在堆上,因为这意味着系统可能不会抛出std::bad_alloc。除此之外,这完全取决于实现:不指定实现(必须记录),但不指定。(实现可以在大多数时间使用堆,只要它有某种紧急备份,即使在没有更多内存的情况下也允许有限数量的异常。)

票数 -2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6611880

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档