metal
написал 8 мая 2008 года в 23:43 (1012 просмотра)
Ведет себя
как мужчина; открыл 31 тему в форуме, оставил 1547 комментариев на сайте.
Вот задумался я, а что будет если исчерпается размер стека, написал маленькую программку:
#include
void f(unsigned long long count)
{
try
{
char buffer[1024 *1024];
std::cout << "count=" << count << 'M' << std::endl;
//sleep(1);
f( count + 1);
}
catch(...)
{
std::cout << "catch exception" << std::endl;
}
}
int main(int argc,char* argv[])
{
f(1);
return 0;
}
Собираю: g++ main.cpp -o pkillself
Результат:
count=1M
count=2M
count=3M
count=4M
count=5M
count=6M
count=7M
Ошибка сегментирования (core dumped)
Собираю: g++ main.cpp -O2 -o pkillself
Результат:
…
count=24945M
count=24946M
count=24947M
count=24948M
count=24949M
count=24950M
count=24951M
Ошибка сегментирования (core dumped)
Вот у меня возникло 2 вопроса:
1) Как недопустить ошибки сегментирования?
2) Откуда такие не реальные объемы памяти?
Последние комментарии
-
OlegL, 17 декабря 2023 года в 15:00 →
Перекличка
21
-
REDkiy, 8 июня 2023 года в 9:09 →
Как «замокать» файл для юниттеста в Python?
2
-
fhunter, 29 ноября 2022 года в 2:09 →
Проблема с NO_PUBKEY: как получить GPG-ключ и добавить его в базу apt?
6
-
Иванн, 9 апреля 2022 года в 8:31 →
Ассоциация РАСПО провела первое учредительное собрание
1
-
Kiri11.ADV1, 7 марта 2021 года в 12:01 →
Логи catalina.out в TomCat 9 в формате JSON
1
DevOps as a Service from Palark
24/7 SRE & DevOps service to cover all your Kubernetes needs.

На Юникс подобных системах ulimit определяет размер стека (стандартно насколько я знаю это 8Мб). Можно попробывать:
ulimit -s unlimited
IMHO не существует стандартного пути для предотвращения seg fault в случае переполнения стека для C/C++. Библиотеки для контроля за переполнением буферов насколько я знаю этим тоже не занимаются.
Вообще лучше всего не использовать рекурсию и большие обьекты в стеке (да Вы и сами это знаете).
Код:
static const int MB = 1024 * 1024; void f(unsigned long long count) { try { char buffer[ MB ]; std::fill( buffer, buffer + MB, '\0' ); std::cout << "count=" << count << 'M' << std::endl; f( ++count ); } catch(...) { std::cout << "catch exception" << std::endl; } }Даст ответ на 2–й вопрос.
Удачи
––– sas
RedZone? Или как там это называется? Посмотри что это такое, потом расскажешь ;)
Функции f
_Z1fy: .LFB1435: pushq %rbx # .LCFI1: movl $.LC0, %esi #, movq %rdi, %rbx # count, count movl $_ZSt4cout, %edi #, .LEHB0: call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc # movq %rax, %rdi #, D.30670 movq %rbx, %rsi # count, count call _ZNSolsEy # movq %rax, %rdi #, D.30671 movl $77, %esi #, call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c # movq %rax, %rdi #, this call _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_ # leaq 1(%rbx), %rdi #, tmp67 call _Z1fy # .LEHE0: popq %rbx # retЭтот код не резервирует место под buffer. По ходу дела, g++ замечательно этот buffer соптимизировал. Каждый рекурсивный вызов откушивает от стека sizeof(long long) байт под аргумент вызова count.
Всем спасибо!
1) По stack redzone, мало что нашел, но в общем идея понятна. Странно что с++ не генерирует ошибку в случае переполнения стека, это было бы логично. Вероятно из соображений проиводительности.
2) Да, что-то я не учел подлянки оптимизации:)
Может ещё C++ будет сборкой мусора заниматься… ;-)
Да вообще занимается если надо.
Во и со стеком точно также. Если надо…
С++ как и С ничего не делает за программера, он тоже расчитан быть использован в системном программировании.