当我扔东西的时候,它在什么地方存储在内存中?
我明白,当有东西throw
n时,堆栈被“解开”到它被捕获的地步,并且在每个函数上下文中堆栈上的类实例的析构函数都被运行(这就是为什么你不应该抛出exception析构函数 – 你可能会抛出第二个)…但是我想知道在存储器中我抛出的对象在这种情况下被存储了吗?
它依赖于实现吗? 如果是这样,那么大多数stream行的编译器是否使用了特定的方法?
是的,答案是依赖于编译器的。
使用我的编译器( g++ 4.4.3
)进行的一个快速实验表明,它的运行时库首先尝试为malloc
内存寻找exception,如果失败,则试图在数据段上的进程范围的“紧急缓冲区”内分配空间。 如果这不起作用,它会调用std::terminate()
。
看起来,紧急缓冲区的主要目的是在进程溢出堆空间(在这种情况下, malloc
调用将失败)之后,能够抛出std::bad_alloc
。
相关的函数是__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)); }
我不知道这个计划有多典型。
从这个页面 :
被抛出的exception需要存储。 这个存储必须在堆栈解开时保持,因为它将被处理器使用,并且必须是线程安全的。 因此,exception对象存储通常会分配在堆中 ,尽pipe实现可能会提供一个紧急缓冲区来支持在低内存条件下抛出bad_allocexception。
现在,这只是安腾ABI,我正在寻找具体到GCC,Clang和MSVC的细节。 但是,标准没有指定任何东西,这似乎是实现exception存储的显而易见的方式,所以…
我不知道这是否会回答你的问题,但是这个(C ++编译器如何实现exception处理)是关于exception处理的绝佳文章。 我强烈推荐它(:
对不起,简短的回答,但文章中的全部信息是伟大的,我不能在这里挑选和发布一些信息。
C ++标准通常指定语言的行为,而不是编译器应该如何实现该行为。 我认为这个问题属于这个范畴。 实现这样的最好的方式取决于机器的细节 – 一些处理器有很多通用寄存器,有些则很less。 一个处理器甚至可以用特殊的寄存器来构buildexception,在这种情况下,编译器应该可以自由地利用这个特性。
那么,它不能在栈上,因为这将被解开,它不能在堆上,因为这意味着系统可能不会抛出std::bad_alloc
。 除此之外,这完全取决于实现:没有指定实现(必须logging),但没有指定。 (一个实现可以在大多数情况下使用堆,只要它具有某种紧急备份,即使没有更多的内存,也可以允许有限数量的exception。