Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.68/25: Рейтинг темы: голосов - 25, средняя оценка - 4.68
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700

Понимание процесса разворачивания стека

24.03.2017, 12:26. Показов 5167. Ответов 18
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Правильно ли я понимаю, что это приблизительно следующее:

Начнем с того что вызовы функций или методов могут быть вложенными и в самом конце завершается первая функция из общей цепочки.

Если где то во вложенном вызове функции возникает исключение, то от стека функции в которой возникло исключение начинается поиск обработчика этого исключения.

При этом все участки памяти (кадры) стека которые не содержат информации об обработчике исключения - освобождаются и в таком же ключе идет поиск вплоть до самого первой функции в поисках обработчика исключения.

Если обработчик найден - очистка кадров останавливается и срабатывает обработчик исключения, а если вообще не найден обработчик - все занятая память на стеке освобождается и программа рушится.

Правильно ли я понимаю процесс stack unwiпdiпg?

Добавлено через 55 минут
Еще читал что если объявить функцию как noexcept то компилятор не генерирует код который нужен для всего этого процесса даже в том случае если в функции есть throw. В этом случае вместо процесса разворачивания стека просто вызывается std::terminate в том случае если дело дойдет до throw - это верно?
1
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
24.03.2017, 12:26
Ответы с готовыми решениями:

Написать процедуру разворачивания стека
Уважаемые форумчане, Нужны решения к нижеприведенным заданиям. Желательно с подробными комментариями. Заранее благодарен. 2....

Структура стек (: добавить элемент в стек, удалить элемент из стека, получить значение с вершины стека, размер стека...)
Всем привет,ребят помогите пожалуйста с лабой,вообще без понятия про стеки:( Может кто то делал,или встречался с таким заданием: ...

Код разворачивания?
Вот карочи я решил по работать с трей иконкой установил компанент и начал писать, написал код только для закрытия и сворачивания программы...

18
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
24.03.2017, 12:38
noexcept говорит компилятору, что можно не сохранять порядок вызова функций и перемешивать их как угодно в целях оптимизации. При этом, если исключение всё же будет брошено, то вызовется std::terminate и нет никакой гарантии, что будут вызваны деструкторы всех созданных объектов.

Добавлено через 1 минуту
Цитата Сообщение от sys_beginner Посмотреть сообщение
Начнем с того что вызовы функций или методов могут быть вложенными и в самом конце завершается первая функция из общей цепочки.
Если отбросить возможную оптимизацию и встраивание, то да.
2
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
24.03.2017, 12:54  [ТС]
Цитата Сообщение от MrGluck Посмотреть сообщение
При этом, если исключение всё же будет брошено, то вызовется std::terminate и нет никакой гарантии, что будут вызваны деструкторы всех созданных объектов.
Но программа ведь завершится и в любом случае все занятые ресурсы будут освобождены, не так ли?

В целом я верно понял смысл разворачивания стека?

И еще вот что интересно. А делают ли так:
Допустим есть функция которую мы хотим объявить как noexcept, сама она не кидает исключения но вызывает другие функции которые не являются noexcept. Но при этом мы согласны на то, что если и будет такое исключение(хотя маловероятно т.к например мы вызываем Сишные функции которые не являются noexcept) то пофиг пусть программа падает т.к для нас больший приоритет имеет наличие noexcept.

Добавлено через 10 минут
То есть несмотря на то что вызываемые функции не имеют гарантий noexcept, тем не менее мы знаем что исключений не будет т.к это СИшные функции а там нет исключений
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
24.03.2017, 13:20
Цитата Сообщение от sys_beginner Посмотреть сообщение
хотя маловероятно т.к например мы вызываем Сишные функции которые не являются noexcept
Как это не являются? Смотрим в стандартные заголовки:
C++
1
2
3
4
//функция определена как __THROW
extern void *malloc (size_t __size) __THROW __attribute_malloc__ __wur;
//__THROW определен как throw(). То есть, "никаких исключений".
#   define __THROW  throw ()]
Цитата Сообщение от sys_beginner Посмотреть сообщение
То есть несмотря на то что вызываемые функции не имеют гарантий noexcept, тем не менее мы знаем что исключений не будет т.к это СИшные функции а там нет исключений
Внезапно, исключения там могут и быть. Например, откройте документацию на WinAPI функцию HeapAlloc и с удивлением посмотрите на флаг HEAP_GENERATE_EXCEPTIONS. Но ага, извращенство.
1
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
24.03.2017, 13:25  [ТС]
Renji,
Понятно, спасибо!
Я имел ввиду не извращенные вещи

Вообще за это я и ненавижу windows. Майкрософт постоянно пытается пропихнуть свои нестандартные придумки польза которых зачастую бывает сомнительной...
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
24.03.2017, 21:09
Цитата Сообщение от sys_beginner Посмотреть сообщение
Правильно ли я понимаю процесс stack unwiпdiпg?
Термин stack unwinding - это более широкое и более абстрактное понятие, к конкретному языку отношения не имеющее. То, что ты описал - это способ использования stack unwinding для реализации exception'ов языка программирования. Причём сами exception'ы могут быть реализованы вообще без использования механизмов unwinding'а, старые компиляторы так и делали, но получалось много накладных расходов в точке вызова функций (exception'ы прилетают редко, а расходы делаются всегда)

При пробрасывании exception'ов через stack unwinding делаются две вещи. На первом проходе по стеку ищется фрэйм стека, который содержит нужный нам catch. На втором проходе по стеку в каждом из фреймов вызываются деструкторы. И только после этого передаётся управление на catch

Я не знаю, следует это из стандартов, или ещё откуда-то, но в современных linux'овых glibc ещё stack unwinding используется при отмене потока через pthread_cancel. В этом случае выполняется только второй проход, который идёт по стеку до точки начала потока и вызывает деструкторы

Цитата Сообщение от sys_beginner Посмотреть сообщение
т.к например мы вызываем Сишные функции которые не являются noexcept
Программа может быть написана на смеси Си и Си++. В стеке коды могут лежать вперемешку. Размотка стека должна уметь проскакивать через фрэймы, соответствующие Си, а потому компилятор Си должен уметь предоставлять дополнительную информацию для раскрутчика стека (у gcc это делается по опции -fexceptions вроде бы). Более того, у gcc в языке Си есть нечто, похожее на деструкторы Си++ - это атрибут cleanup - https://gcc.gnu.org/onlinedocs... Attributes. Т.е. при пролёте исключения через фрэйм на Си может быть вызвана cleanup-функция

Добавлено через 2 минуты
Цитата Сообщение от sys_beginner Посмотреть сообщение
Допустим есть функция которую мы хотим объявить как noexcept, сама она не кидает исключения но вызывает другие функции которые не являются noexcept
По-моему, если из вызыванных функций вылетает исключение, которое мы не ловим в текущей фунции (которая является noexcept), то в этом случае программа обязана падать по стандарту. Т.е. noexcept (ну или trow() в старых стандартах) - это некий фильтр, а если через фильтр попытается пролететь исключение, то программа должна ломаться
4
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
24.03.2017, 21:35
Цитата Сообщение от Evg Посмотреть сообщение
Размотка стека должна уметь проскакивать через фрэймы, соответствующие Си, а потому компилятор Си должен уметь предоставлять дополнительную информацию для раскрутчика стека
Корректное проскакивание сишных фреймов с пометкой "No exception safety" не возможно по крайней мере до тех пор, пока в компилятор не встроят искусственный интеллект. А такая пометка там с вероятностью процентов 90%.
C++
1
2
3
4
5
6
7
8
9
void CFunction()
{
    //открыли файл
    FILE*myFile=fopen("1234.txt");
    //полетело исключение
    someFunction();
    //закрыли файл... Опс, не закрыли, ведь полетело исключение
    fclose(myFile);
}
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
24.03.2017, 22:06
Под "проскакиваением через Сишный фрейм" я имею в виду то, что размотка стека должна продолжаться, а не ломаться. И чтобы она продолжилась, то фрэйм должен содержать информацию CFI (Call Frame Info). Это место зависит от конкретной архитектуры, но, тем не менее, в общем случае если компилятор инфу не предоставит, то размотка стека прекратится с каким-нибудь аварийным сообщением. Тупо потому, что размотчик стека не будет знать, как пойти дальше по стеку. В gcc на интеле опция -fexceptions по умолчанию включена и как-то там нужно было помучться, чтобы отключить (где-то на форуме я выкладывал результат, с ходу что-то не могу найти), а потому просто так не поэкспериментируешь

Добавлено через 28 секунд
Как-то там надо было комбинировать с опциями -fno-exceptions -fno-unwind-tables или что-то типа того. Под рукой нету gcc
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
24.03.2017, 22:08
Цитата Сообщение от Evg Посмотреть сообщение
Под "проскакиваением через Сишный фрейм" я имею в виду то, что размотка стека должна продолжаться, а не ломаться.
Это понятно. Я про то что смысла в таком продолжении нет, так как при броске исключения через сишный код данные один фиг придут в некорректное состояние и программа упадет. Тут как раз аварийное сообщение будет вполне достаточным. Или даже просто пометка о UB в случае подобных бросков.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
24.03.2017, 22:15
Цитата Сообщение от Renji Посмотреть сообщение
так как при броске исключения через сишный код данные один фиг придут в некорректное состояние
А это уже от афтора программы зависит
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
24.03.2017, 22:24
Цитата Сообщение от Evg Посмотреть сообщение
А это уже от афтора программы зависит
Вряд ли. Если бы автор рассчитывал на использование механизма исключений, он бы писал на плюсах, а не Си.
0
42 / 42 / 17
Регистрация: 25.04.2014
Сообщений: 499
25.03.2017, 03:00
Цитата Сообщение от sys_beginner Посмотреть сообщение
Правильно ли я понимаю, что это приблизительно следующее:
добавлю, что при throw something этот объект something должен где-то сохраниться чтобы быть валидным при раскрутке стека... был бы признательным если б кто-то толково объяснил где и как он сохраняется
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
25.03.2017, 14:35
Цитата Сообщение от tapochka Посмотреть сообщение
добавлю, что при throw something этот объект something должен где-то сохраниться чтобы быть валидным при раскрутке стека... был бы признательным если б кто-то толково объяснил где и как он сохраняется
C++
$ cat t.cc
void foo (void)
{
  throw int(-1);
}
Code
$ g++ t.cc -O1 -S
$ cat t.s
...
_Z3foov:
.LFB0:
        .cfi_startproc
        subl    $28, %esp
        .cfi_def_cfa_offset 32
        movl    $4, (%esp)
        call    __cxa_allocate_exception
        movl    $-1, (%eax)
        movl    $0, 8(%esp)
        movl    $_ZTIi, 4(%esp)
        movl    %eax, (%esp)
        call    __cxa_throw
        .cfi_endproc
.LFE0:
Т.е. память выделяется динамически. Вот код функции __cxa_allocate_exception

C++
extern "C" void *
__cxxabiv1::__cxa_allocate_exception(std::size_t thrown_size) _GLIBCXX_NOTHROW
{
  void *ret;
 
  thrown_size += sizeof (__cxa_refcounted_exception);
  ret = malloc (thrown_size);
 
  if (!ret)
    ret = emergency_pool.allocate (thrown_size);
 
  if (!ret)
    std::terminate ();
 
  memset (ret, 0, sizeof (__cxa_refcounted_exception));
 
  return (void *)((char *)ret + sizeof (__cxa_refcounted_exception));
}
Добавлено через 9 минут
По поводу смеси кода на Си и Си++. gcc под sparc в режиме Си по умолчанию НЕ делает никаких телодвижений по сохранению CFI (Call frame info). В gcc под intel они всё-таки включили по умолчанию, поэтому для интела нужно будет подавать дополнительную опцию -fno-asynchronous-unwind-tables, чтобы сымитировать поведение по умолчанию компилятора с "Си без поддержки проброса исключений". Во всяком случае в моём gcc-4.8.0 нужно использовать именно эту опцию

C++
/* Файл t1.cc */
void foo (void)
{
  throw int(1);
}
 
extern "C" void bar (void (*)(void));
 
int main (void)
{
  try
  {
    bar (foo);
  } catch (int)
  {
  }
 
  return 0;
}
C
/* Файл t2.c */
void bar (void (*fptr)(void))
{
  fptr();
}
Code
# Вариант без поддержки проброса исключений в модуле на Си
$ g++ -c t1.cc
$ gcc -c -fno-asynchronous-unwind-tables t2.c
$ g++ t1.o t2.o
$ ./a.out
terminate called after throwing an instance of 'int'
Aborted
 
# Вариант с поддержкой проброса исключений в модуле на Си
# (в компилятор Си подаём опцию -fexceptions)
$ g++ -c t1.cc
$ gcc -c -fno-asynchronous-unwind-tables -fexceptions t2.c
$ g++ t1.o t2.o
$ ./a.out
<ok>
Добавлено через 10 минут
Модификация файла t2.c для того, чтобы засветить возможность вызова деструкторов в коде на Си, через который пролетает C++ exception или проход по стеку в случае отмены потока

C
/* Файл t2.c */
#include <stdio.h>
 
void qux (int *p)
{
  printf ("qux\n");
}
 
void bar (void (*fptr)(void))
{
  int x __attribute__((cleanup(qux)));
  fptr();
}
Code
$ g++ -c t1.cc
$ gcc -c -fno-asynchronous-unwind-tables -fexceptions t2.c
$ g++ t1.o t2.o
$ ./a.out
qux
Добавлено через 2 минуты
Если убрать опцию -fexceptions (и -fno-asynchronous-unwind-tables), то деструктор в Си не будет вызыван. Поскольку компилятор в режиме Си без опции -fexceptions не делает никаких телодвижений для обеспечения вызова деструктора при транзитном пролёте исключений
2
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
25.03.2017, 14:36
Цитата Сообщение от Evg Посмотреть сообщение
Т.е. память выделяется динамически.
Нда, я прям так и вижу сообщение об ошибке - "невозможно выполнить обработчик std::bad_alloc, по причине нехватки динамической памяти".
Лучше бы прописали в стандарт что память выделяется из thread_local буфера, вмещающего в себя не менее 4*sizeof(void*) байт (указатель на строчку для what+еще чего по мелочи). И разрешили компилятору запрещать бросать исключения превышающие по размеру вышеупомянутый буфер.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
25.03.2017, 15:14
В стандарте вряд ли прописано, где да как должна выделяться память, это уже компилятор решает. Напиши аналогичный тест, но не с int'ом, а с std::bad_alloc (к сожалению, мои знания в Си++ не позволяют понять, как это сделать). Возможно, что код уже будет другим, т.е. без вызова __cxa_allocate_exception

Добавлено через 31 минуту
Цитата Сообщение от Renji Посмотреть сообщение
Нда, я прям так и вижу сообщение об ошибке - "невозможно выполнить обработчик std::bad_alloc, по причине нехватки динамической памяти"
Кстати, там код:

C++
if (!ret)
    ret = emergency_pool.allocate (thrown_size);
т.е. у них есть какая-то заранее зарезервированная песочница (естественно, не бесконечная) для таких случаев
0
42 / 42 / 17
Регистрация: 25.04.2014
Сообщений: 499
04.04.2017, 01:22
Evg, а можете осветить еще пару моментов?
1) вот, допустим, такое:
C++
1
2
3
4
5
6
7
8
9
10
void foos() throw() {
  throw 1;
}
 
int main() {
   try {
       foos();
   } catch(...) {
   }
}
сгенерируется на gcc 6.3 x86_64 в это:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
foos():
        movl    $4, %edi
        subq    $8, %rsp
        call    __cxa_allocate_exception
        xorl    %edx, %edx
        movl    $1, (%rax)
        movl    typeinfo for int, %esi
        movq    %rax, %rdi
        call    __cxa_throw
        addq    $1, %rdx
        movq    %rax, %rdi
        je      .L16
        call    _Unwind_Resume
можете чуток более подробно механизм unwind_resume объяснить(которая появляется только если throw() всобачить... без throw() и, в том числе, с noexcept этого нету)? вот такого как-то недостаточно:
_Unwind_Resume resumes propagation of an existing exception object. A call to this routine is inserted as the end of a landing pad that performs cleanup, but does not resume normal execution. It causes unwinding to proceed further.
2) если foos без throw, то код выше дает это:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
foos():
        movl    $4, %edi
        subq    $8, %rsp
        call    __cxa_allocate_exception
        xorl    %edx, %edx
        movl    $1, (%rax)
        movl    typeinfo for int, %esi
        movq    %rax, %rdi
        call    __cxa_throw
main:
        subq    $8, %rsp
        call    foos()
        movq    %rax, %rdi
        call    __cxa_begin_catch
        call    __cxa_end_catch
        xorl    %eax, %eax
        popq    %rcx
        ret
почему __cxa_begin_catch вызывается после foos а не перед ней? как-то нелогично это
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
04.04.2017, 22:23
Сам по себе код отфильтрованный код смотреть не особенно интересно. Его нужно смотреть его вместе с обвесом, который описывает Call Site'ы (диапазоны адресов, из-под которых может прилететь исключение) и Landing Pad'ы (точки, куда приземляется управление при пролёте исключения). Правда я не настолько хорошо во всём этом разбираюсь

Если взять более обобщённый случай (тут даже catch'ей нет):

C++
void bar (void);
 
void foo (void) throw (int)
{
  bar();
}
Code
$ gcc-4.8.0 t.cc -O3 -S
$ cat t.s
Из-под вызова bar может прилететь исключение любого типа. Функция foo описана со спецификатором throw(int), а потому нужно пропустить через себя (т.е. отправить наверх) прилетевшее из bar исключение типа int и вызвать слом для любого другого типа исключения. Я понимаю общий принцип, но точные детали сказать затрудняюсь

Code
        .file   "t.cc"
        .text
        .p2align 4,,15
        .globl  _Z3foov
        .type   _Z3foov, @function
_Z3foov:
.LFB0:
        .cfi_startproc
        .cfi_personality 0,__gxx_personality_v0
        .cfi_lsda 0,.LLSDA0
        subl    $28, %esp
        .cfi_def_cfa_offset 32
 
        # Вокруг Call'а стоят метки, описывающие Call Site, они использованы
        # ниже в таблице, описывающей технику размотки стека при исключении
        # Через эти метки описан диапазон адресов, в какой программа бы вернулась
        # при нормальном выходе (через return) из Call'а
.LEHB0:
        call    _Z3barv
.LEHE0:
 
        # Если мы выходим из Call'а через return, то мы просто выполняем
        # return в текущей процедуре (т.е. следующая за Call'ом операция)
        addl    $28, %esp
        .cfi_remember_state
        .cfi_def_cfa_offset 4
        ret
 
        # Метка .L4 описывает Landing Pad - точку, куда вернётся управление,
        # если из bar'а вернёмся не через return, а через исключение
        # Сюда должны прийти два параметра (скорее всего на регистрах):
        # N1. адрес объекта, который был брошен в исключении
        # N2. не помню что (какой-то selector), но, грубо говоря, некоторая информация,
        # на основании которой компилятор поймёт, прилетело исключение хорошего типа
        # (т.е. можно прокинуть его дальше) или плохого типа (т.е. надо сломаться).
        # Или что-то в этом роде
.L4:
 
        .cfi_restore_state
 
        # Вероятно, по результату этой операции отработает нижеидущий je
        addl    $1, %edx
 
        # Вероятно, подготовка параметра для двух нижеидущих call'ов
        # Вызовется только один из них, но у обоих одинаковый параметр
        movl    %eax, (%esp)
        je      .L3
 
.LEHB1:
        # Прилетело хорошее исключение, вызываем _Unwind_Resume, который
        # продолжит разматывать стек. В него передаётся параметр N1
        call    _Unwind_Resume
.L3:
        # Прилетело плохое исключение, надо сломаться
        # В этот вызов передаётся только параметр N1
        call    __cxa_call_unexpected
.LEHE1:
        .cfi_endproc
.LFE0:
 
 
        .globl  __gxx_personality_v0
        .section        .gcc_except_table,"a",@progbits
        .align 4
.LLSDA0:
        .byte   0xff
        .byte   0
        .uleb128 .LLSDATT0-.LLSDATTD0
.LLSDATTD0:
        .byte   0x1
        .uleb128 .LLSDACSE0-.LLSDACSB0
 
        # Начало таблицы Landing Pad'ов
.LLSDACSB0:
 
        # Запись в таблице, говорящяя, что если раскрутчик стека видит,
        # что если прилетело исключение из-под операции Call, которая нормально
        # вернулась бы в диапазон адресов .LEHB0 - .LEHE0 (т.е. так описывается
        # операция Call bar), то нужно пойти на Landing Pad, описанный меткой .L4
        # Последняя единичка описывает Action 1 (см. ниже)
        .uleb128 .LEHB0-.LFB0
        .uleb128 .LEHE0-.LEHB0
        .uleb128 .L4-.LFB0
        .uleb128 0x1
 
        # Следующая запись в таблице
        .uleb128 .LEHB1-.LFB0
        .uleb128 .LEHE1-.LEHB1
        .uleb128 0
        .uleb128 0
 
        # Начало таблицы Action'ов
.LLSDACSE0:
        # Action 1
        # Тут закодирована информация, что нужно фильтровать тип 1 (см. ниже)
        .byte   0x7f
        .byte   0
 
        .align 4
        # Тип 1 (int). Описывается в виде указателя на typeinfo-объект
        .long   _ZTIi
        # Middle-point таблицы типов. Вверх растут описания типов
.LLSDATT0:
        .byte   0x1
        .byte   0
        .text
        .size   _Z3foov, .-_Z3foov
        .ident  "GCC: (GNU) 4.8.0"
        .section        .note.GNU-stack,"",@progbits
У меня записаны полезные ссылки:
http://www.airs.com/blog/archives/464
http://mentorembedded.github.i... ptions.pdf

Вторая ссылка уже битая. Если на работе остался pdf, то выложу. При прочтении обоих документов в несколько итераций можно понять общий принцип и понимать, как читать код из-под компилятора. На моей памяти код из-под clang'а читать намного удобнее, т.к. таблица там отмечена внятными комментариями. Но у clang'а и gcc немного разные модели того, как нужно ломаться в случае неправильного исключения, поэтому код будет немного разный

Добавлено через 19 минут
Перед меткой .L4 поправил комментарий (неправильно был описан параметр N1)
1
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12944 / 6811 / 1821
Регистрация: 18.10.2014
Сообщений: 17,236
05.04.2017, 03:37
Цитата Сообщение от sys_beginner Посмотреть сообщение
Если где то во вложенном вызове функции возникает исключение, то от стека функции в которой возникло исключение начинается поиск обработчика этого исключения.
Да.

Цитата Сообщение от sys_beginner Посмотреть сообщение
При этом все участки памяти (кадры) стека которые не содержат информации об обработчике исключения - освобождаются и в таком же ключе идет поиск вплоть до самого первой функции в поисках обработчика исключения.

Если обработчик найден - очистка кадров останавливается и срабатывает обработчик исключения, а если вообще не найден обработчик - все занятая память на стеке освобождается и программа рушится.

Правильно ли я понимаю процесс stack unwiпdiпg?
Это не обязательно так. Возможна реализация, которая в случае выброса исключения сначала производит поиск обработчика. И только если обработчик найден, то только после этого выполняется раскрутка стека до уровня найденного обработчика и передача управления в обработчик. Если же обработчика не найдено, то сразу вызывается std::terminate без раскрутки стека. (Будет ли в таких случаях раскрутка - определяется реализацией.)

Цитата Сообщение от sys_beginner Посмотреть сообщение
Еще читал что если объявить функцию как noexcept В этом случае вместо процесса разворачивания стека просто вызывается std::terminate в том случае если дело дойдет до throw - это верно?
Верно.
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
06.04.2017, 09:32
Цитата Сообщение от Evg Посмотреть сообщение
Вторая ссылка уже битая
У них документация переехала на новое место жительства
https://itanium-cxx-abi.github... ptions.pdf
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
06.04.2017, 09:32
Помогаю со студенческими работами здесь

Задан указатель P1 на вершину непустого стека. Создать два новых стека
Добрый вечер, у меня возникла проблемка с такой программкой. Вывести в компонент Label. Буду очень очень благодарен. ...

Создать два новых стека, с четными и нечетными элементами первоначального стека
Дано указатель P1 на вершину непустого стека. Создать два новых стека , переместив в первый из них все элементы исходного стека с четными...

Из одного стека, хранящего символы, создать два новых стека
Из одного стека, хранящего символы, создать два новых стека: один с латинскими буквами, удвоив каждую из них, другой со всеми остальными...

Из одного стека, хранящего символы, создать два новых стека
Из одного стека, хранящего символы, создать два новых стека: один с латинскими буквами, удвоив каждую из них, другой со всеми остальными...

Считать из стека верхний элемент и меняет значение переменной стека
Нужно определить макрос, который читает из стека верхний элемент и меняет значение переменной стека


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Новые блоги и статьи
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru