Я понимаю, что когда что-то throw
n, стек `` разматывается '' до точки, где он был пойман, и запускаются деструкторы экземпляров класса в стеке в каждом контексте функции (вот почему вы не должны генерировать исключение из деструктора - вы могли бы бросить второй) ... но мне интересно, где в памяти хранится брошенный мною объект, когда это происходит?
Это зависит от реализации? Если да, то есть ли какой-то конкретный метод, используемый наиболее популярными компиляторами?
c++
exception
exception-handling
sje397
источник
источник
raise
его), уничтожьте его. Проблема с распределением кучи заключается в следующем: что делать, если попытка выделить исключение не удалась? Вам придется прервать выполнение (так же, как и при переполнении стека, если поместить его в стек "не удается" из-за нехватки места). В отличие от Java, реализация не может вместо этого генерировать другое исключение.Ответы:
Да, ответ зависит от компилятора.
Быстрый эксперимент с моим compiler (
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)); }
Не знаю, насколько типична эта схема.
источник
malloc
вызов завершится неудачно" - обычно, но не обязательно.С этой страницы :
Теперь это только Itanium ABI, и я ищу подробности, относящиеся к GCC, Clang и MSVC. Однако стандарт ничего не определяет, и это кажется очевидным способом реализации хранилища исключений, так что ...
источник
Я не знаю, ответит ли это на ваш вопрос, но это (Как компилятор C ++ реализует обработку исключений) отличная статья об обработке исключений вообще:. Очень рекомендую (:
Извините за короткий ответ, но вся информация в статье отличная, я не могу выбрать и опубликовать здесь какую-то информацию.
источник
excpt_info
этой странице информацию о том, как это делает MSVC.Стандарт C ++ обычно определяет поведение языка, но не то, как компилятор должен реализовать это поведение. Я думаю, что этот вопрос попадает в эту категорию. Наилучший способ реализовать что-то подобное зависит от специфики машины - у некоторых процессоров много регистров общего назначения, у некоторых их очень мало. Процессор может быть даже построен со специальным регистром только для исключений, и в этом случае компилятор должен иметь возможность воспользоваться этой функцией.
источник
Ну, он не может быть в стеке, так как он будет раскручиваться, и он не может быть в куче, поскольку это будет означать, что система, скорее всего, не сможет выбросить
std::bad_alloc
. В остальном это полностью зависит от реализации: реализация не указана (которая должна быть задокументирована), а не указана. (Реализация может использовать кучу большую часть времени, если у нее есть какое-то аварийное резервное копирование, которое допускает ограниченное количество исключений, даже если памяти больше нет.)источник
std::bad_alloc
для работы. Это означает, что реализация не может систематически использовать кучу. Стандарт этого не позволяет. Я основываю свои претензии на стандарте.