Обработка StackOverflow

Давайте не будем ссориться. Мы же одна команда, разве нет?

Вам надо уточнить в словаре значение слова “гипербола”.

А вот указывать, что мне надо и что нет - это уже начало действительно хамства.

<личное мнение>Полезная вещь. Почитайте на досуге. :slight_smile:</личное мнение>

Ключевое слово checked используется для явного включения проверки переполнения при выполнении арифметических операций и преобразований с данными целого типа.

Взято отсюда.

Это к тому, что System.StackOverflowException и checked никак не коррелируют.

Если же рассматривать вопрос о нужности checked - то не сказал бы, что это очень нужно. К примеру, Visual Studio без checked можно настроить выброс этого исключения. Мое мнение по этому поводу - нейтрально. Поэтому если другие хотят высказаться, то пускай.

Слушайте, это ведь уже параноя…

В данном случае никто не говорил про него, просто привели программу с ним. На паскале это тоже можно сделать, но на C# выглядит проще, поэтому на нём пример.

@RAlex, я стараюсь не говорить людям о их недостатках так прямо, но давайте вы будете контролировать себя, когда кто то говорит о фиче из другого языка.

Конечно, то что она хорошо в другом языке - не значит что её надо тянуть в паскаль.
Но и сам факт что она из другого языка - не значит что надо сразу говорить про то чтоб её в паскаль не добавляли.

Надо хотя бы привести нормальные аргументы, а не “гиперболы” и прочие простите, но выебоны.




Кстати, я добавил

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

Не стоит начинать неконструктивную беседу, либо провоцировать на неё. Это относится ко всем. Печально наблюдать, как пользователи нарушают это правила. У нас приличный форум. Так почему другие должны читать наши разборки? Тем более, последние сообщения отображаются здесь.

2 лайка

Вопрос этот всплыл по ходу исследовательской работы, в которой предельная глубина рекурсии (переполнение стека) должна была фиксироваться, а программа при этом не должна была падать. И довольно странно было обнаружить, что обещанная обработка StackOverflowException не работает. Ни о какой неконтролируемой рекурсии в реальных программах речь не идет.

А можно подробнее, что за исследования?)) Или вы имеете в виду самообучение?

Но, кстати такого не существует.

Стек - это объём памяти, похожей на оперативную, но стек находится ближе к процессору, поэтому работа с ним получается быстрее.

Когда вызывается какой то метод - под координаты точки откуда он был вызван + его внутренние переменные (для value-типов. под ссылочные типы выделяет лишь место под ссылку) выделяет место на стеке. А если места не хватает - получаем это исключение.

Вот только разные методы требуют разный объём памяти под свои переменные. И там ещё разные другие факторы могут быть замешаны.

Но, в общем, чёткого предела не существует.

Исследования - это громко сказано. Учебное студенческое задание, в которое студент, проявив инициативу, захотел внедрить автоматическое обнаружение переполнения стека. Словом “исследование” просто хотел подчеркнуть, что это не прикладная программа.

В лекции про стек необходимости не было.

“Но, кстати такого не существует.”

  • для каждой конкретной программы (процедуры) в конкретной среде существует.

Ну, я недавно читал как можно узнать какой объём стека остался на раздачу - там вроде можно какими то костылями + WinAPI (но из за костылей - там какая то погрешность, в общем только примерно узнать можно), ищите на msdn+StackOverflow

В вашем предложении все 3 тезиса неверные:

  1. стек не похож на оперативную память, он и есть просто область в оперативной памяти, выделяемая системой для каждого процесса отдельно;
  2. для архитектуры DRAM не существует такого понятия как “ближе к процессору”;
  3. в общем случае скорость работы со стеком ничем не отличается от скорости работы с любым другим участком оперативной памяти, за исключением нюансов с аппаратным кэшированием внутри процессора при обращении к данным стека.

Системный стек – это небольшой непрерывный участок памяти (у каждого процесса в системе он свой отдельный!). Когда происходит считывание из ОЗУ в регистры процессора какой-то локальной переменной, то реально перед этим в аппаратный кэш читается бОльший объем – минимум страница памяти (напр., 4КБ, но зависит от конкретной архитектуры и настроек системы). Кроме того, у процессоров есть такая фича, как упреждающее чтение смежных адресов и адресов, предсказанных блоком предсказания ветвлений (branch predictor unit).

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

Это называется критерием локальности данных (data locality), и в случае работы с небольшим непрерывным стеком этот критерий обычно намного лучше, чем при работе с большой динамической кучей с произвольно разбросанными по ней данными. Кроме того, при чтении данных из стека используется прямая адресация, а не косвенная (известная в Паскале как разыменование указателя), что также быстрее (по сравнению с обращением к структурам ссылочных типов, хранящихся в куче).

Никаких иных преимуществ в хранении данных именно на системном стеке нет. А вот недостаток очевидный – его сильно ограниченный объем. А случае с .NET есть еще 2 значительных недостатка – невозможность явно повлиять на размер создаваемого системой стека (в отличие напр. от Java или Free Pascal) и невозможность даже перехватить исключение в случае его переполнения. :frowning:

5 лайков

Всё познаётся в сравнении.

Дополню. Сравнение языков вполне уместно, так как они:

  1. Оба основаны на .Net
  2. Имеют похожий синтаксис

Тем более сравнение языков - еще один метод изучения конкретного языка.

1 лайк

Касательно исключения и не только - программист должен сам понимать, что пишет, даже если работает под .NET. Соломки на все возможные случаи не напасёшься. Рекурсию стараются избегать во всех языках, просто в .NET есть ещё один аргумент против - отсутствие оптимизации.

Не сказал бы. Если описывать рекурсию явно, имеется ввиду не вручную через Stack<T>, например, то компилятор имеет возможность провести оптимизацию. При описании, что называется вручную, компилятор не имеет понятия даже о том, что Вы описывайте рекурсию. Поэтому, на мой взгляд, лучше всего знать меру - когда прибегать к рекурсии, а когда имитировать её через стек. При большой вероятности переполнения стека - лучше проводить имитацию.

1 лайк

Но, чаще всего, её как раз вручную и описывают.

Если Вы имейте ввиду какие-нибудь серьезные проекты, то, да, вполне себе хороший подход. При обучении же прибегают к двум подходам. На первых курсах, например, университета используют подход без Stack<T>, так как он более интуитивно понятен, например, новичкам.

Какой?