Sí, la respuesta depende del compilador.
Un experimento rápido con mi compilador ( g++ 4.4.3
) revela que su biblioteca de tiempo de ejecución primero intenta malloc
memorizar la excepción y, en su defecto, intenta asignar espacio dentro de un "búfer de emergencia" de todo el proceso que vive en el segmento de datos. Si eso no funciona, llama std::terminate()
.
Parece que el propósito principal del búfer de emergencia es poder lanzar std::bad_alloc
después de que el proceso se haya quedado sin espacio de almacenamiento dinámico (en cuyo caso la malloc
llamada fallaría).
La función relevante es __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 ();
}
__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));
}
No sé qué tan típico es este esquema.