Предположим, где-нибудь, в каком-нибудь месте программы (не в начале), у нас есть следующий код: int a = <некое значение>; Но до этого места, скажем, в нашей программе уже было несколько сот других переменных и программа много раз обращалась к динамической памяти. Возможна ли такая ситуация, что в системе закончится память, и вышеприведенный код приведен к выработке необрабатываемого исключения и аварийному завершению программы? Либо же до этого new[] уже успеет вызвать std::bad_alloc и такая ситуация в принципе невозможна? Другими словами, есть ли гарантия отсутствия исключений в данном случае? Собственно говоря, инструкция int a = some_val просто транслируется в ассемблерную команду наподобии mov eax, ds[index]; т.е. по идее исключение быть и не должно, вопрос только в том, резервируется ли сегмент данных полностью до начала работы программы для всех переменных либо же приобретение ресурсов происходит динамически, в ходе работы программы, как в случае с динамической памятью. Получается, чем больше у нас имен переменных, тем больше индексов в программе, по которым происходит обращение, и тем больше должен быть объем резервируемого сегмента данных. Правда все равно остается вопрос, как запрашивается сегмент данных - либо он представляет некую область в коде программы (секцию данных), либо же размер для сегмента данных и его размер будут получены из системной кучи, при запуске программы.
Ответ
Если я правильно понял вопрос, то есть код:
func() {
...
int a = 22;
...
}
В таком случае память для переменной a будет размещаться в стеке и "выделяться" при входе в процедуру func.
Я пишу "память выделяется" в кавычках, т.к. при входе в func регистр указателя стека просто будет сдвинут (реально уменьшен) на суммарный объем локальных переменных. Т.о. при обращении к a возможно прерывание по переполнению стека. (Еще вероятнее оно произойдет при вызове первой же функции, если стек в func переполнится).
Размер выделяемого сегмента данных под стек (он выделяется при порождении процесса) и возможность управления этим размером зависит от ОС и ее настроек. По умолчанию в Windows это 2MB, в Linux около 10MB.
Будет ли средой C++ в таком случае вброшено исключение, откровенно говоря, не знаю.
Если интересно, можете поиграться с программкой
#include
void
sigh (int s)
{
write(1,"catch
",6);
exit(1);
}
main (int ac, char *av[])
{
int sz = av[1]? atoi(av[1]): -1;
while (sz < 1) {
printf ("Enter size
");
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
",sz,sz);
char a[sz];
a[0] = 'a';
printf ("first
");
a[sz-1] = 'z';
printf ("last
");
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)
", 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)
", rc,
(long)lim.rlim_cur,(long)lim.rlim_max);
и посмотреть, как это работает.
Комментариев нет:
Отправить комментарий