我知道当某些东西是 throw
n 时,堆栈会“展开”到它被捕获的点,并且每个函数上下文中堆栈上的类实例的析构函数都会运行(其中这就是为什么你不应该从析构函数中抛出异常 - 你最终可能会抛出第二个异常)......但我想知道在这种情况发生时我抛出的对象存储在内存中的哪个位置?
它是否依赖于实现?如果是这样,是否有最流行的编译器使用的特定方法?
最佳答案
是的,答案取决于编译器。
对我的编译器 (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));
}
我不知道这个方案有多典型。
关于c++ - 当我 `throw` 某事时,它存储在内存中的什么位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6611880/