#исключения #cpp
Предположим, где-нибудь, в каком-нибудь месте программы (не в начале), у нас есть
следующий код:
int a = <некое значение>;
Но до этого места, скажем, в нашей программе уже было несколько сот других переменных
и программа много раз обращалась к динамической памяти.
Возможна ли такая ситуация, что в системе закончится память, и вышеприведенный код
приведен к выработке необрабатываемого исключения и аварийному завершению программы?
Либо же до этого new[] уже успеет вызвать std::bad_alloc и такая ситуация в принципе
невозможна?
Другими словами, есть ли гарантия отсутствия исключений в данном случае?
Собственно говоря, инструкция int a = some_val просто транслируется в ассемблерную
команду наподобии mov eax, ds[index]; т.е. по идее исключение быть и не должно, вопрос
только в том, резервируется ли сегмент данных полностью до начала работы программы
для всех переменных либо же приобретение ресурсов происходит динамически, в ходе работы
программы, как в случае с динамической памятью.
Получается, чем больше у нас имен переменных, тем больше индексов в программе, по
которым происходит обращение, и тем больше должен быть объем резервируемого сегмента
данных.
Правда все равно остается вопрос, как запрашивается сегмент данных - либо он представляет
некую область в коде программы (секцию данных), либо же размер для сегмента данных
и его размер будут получены из системной кучи, при запуске программы.
Ответы
Ответ 1
Если я правильно понял вопрос, то есть код: func() { ... int a = 22; ... } В таком случае память для переменной a будет размещаться в стеке и "выделяться" при входе в процедуру func. Я пишу "память выделяется" в кавычках, т.к. при входе в func регистр указателя стека просто будет сдвинут (реально уменьшен) на суммарный объем локальных переменных. Т.о. при обращении к a возможно прерывание по переполнению стека. (Еще вероятнее оно произойдет при вызове первой же функции, если стек в func переполнится). Размер выделяемого сегмента данных под стек (он выделяется при порождении процесса) и возможность управления этим размером зависит от ОС и ее настроек. По умолчанию в Windows это 2MB, в Linux около 10MB. Будет ли средой C++ в таком случае вброшено исключение, откровенно говоря, не знаю. Если интересно, можете поиграться с программкой #include#include #include #include #include void sigh (int s) { write(1,"catch\n",6); exit(1); } main (int ac, char *av[]) { int sz = av[1]? atoi(av[1]): -1; while (sz < 1) { printf ("Enter size\n"); scanf("%d",&sz); } struct sigaction sa; memset (&sa,0,sizeof(sa)); sa.sa_handler = sigh; #ifdef ALTST sa.sa_flags = SA_ONSTACK; stack_t ss; ss.ss_sp = malloc(ss.ss_size=1000000); ss.ss_flags = 0; sigaltstack(&ss,NULL); #endif sigaction(SIGSEGV,&sa,NULL); printf ("Try %d (%x) size\n",sz,sz); char a[sz]; a[0] = 'a'; printf ("first\n"); a[sz-1] = 'z'; printf ("last\n"); exit (0); } avp@avp-ubu1:~/hashcode$ g++ stacksz.c avp@avp-ubu1:~/hashcode$ ./a.out 10400000 Try 10400000 (9eb100) size first last avp@avp-ubu1:~/hashcode$ ./a.out 10500000 Try 10500000 (a037a0) size Ошибка сегментирования avp@avp-ubu1:~/hashcode$ g++ -DALTST stacksz.c avp@avp-ubu1:~/hashcode$ ./a.out 10500000 Try 10500000 (a037a0) size catch avp@avp-ubu1:~/hashcode$ Идея, надеюсь, понятна. Добавьте ловлю исключений и т.п. крестовые штучки. UPDATE Если кому-то интересно, то можно добавить код struct rlimit lim; int rc = getrlimit(RLIMIT_STACK,&lim); printf ("get = %d stsize: %ld (soft) %ld (hard)\n", rc, (long)lim.rlim_cur,(long)lim.rlim_max); int m = av[2]? atoi(av[2]): 1000000; lim.rlim_cur += m; rc = setrlimit(RLIMIT_STACK,&lim); if (rc < 0) perror("setrlimit"); rc = getrlimit(RLIMIT_STACK,&lim); printf ("get2 = %d stsize: %ld (soft) %ld (hard)\n", rc, (long)lim.rlim_cur,(long)lim.rlim_max); и посмотреть, как это работает. Ответ 2
О каком динамическом выделении памяти вообще речь? Место для глобальных переменных резервируется заранее, независимо от области их видимости (это, кстати, хорошо знают те, кому слова tiny, small, compact, medium, large и huge ещё о чём-то говорят ;-) Локальне переменные размещаются в стеке, а в случае оптимизации кода могут и стека не требовать.Ответ 3
Если речь идет о С++, то конструкция int a = <некое значение>; выделяет память на стеке. Учите мат. часть. Размер стека есть величина вполне конкретная и зависит от многих факторов: компилятор, операционная система и пр. И в принципе, это значение может быть увеличено. Я сам пользовался порой черной магией и увеличивал размер стека. Это преимущественно нужно было при использовании рекурсии. Для этого использовалась конструкция #pragma. Почитать конкретнее можно тут.
Комментариев нет:
Отправить комментарий