Обновить

Избавляемся от ошибок Segmentation fault из-за переполнения стека в С++

Уровень сложностиСложный
Время на прочтение10 мин
Охват и читатели8K
Всего голосов 5: ↑2 и ↓3-1
Комментарии13

Комментарии 13

Стек и рекурсия по-сути две стороны одной медали. Плюс многопроцессорность и безопасность стека при работе с общей памятью, плюс кеш, плюс каналы DMA, там же вызов прерываний, если ещё имеется защищённый режим - своп при очень большом стеке (да, часть стека скидывается на диск как при malloc(1 GB) ), особенно когда имеется режим реалтайм это создаёт дополнительные вопросы, поскольку время чтения/записи стека не гарантировано нигде. Поэтому лучшее решение проблем - гарантированное управление памятью по-соседству с исполняемым кодом, исключать любые лямбды и впихивание в стек гигабайтных объектов за счёт копирования контекста, особенно при применении стек-очередей. Вообще говоря отсутствие управления стека, регистров аргументов функций на уровне компилятора и статических языковых конструкций - это боль длящаяся ещё из 80-х, когда зачем-то эту опцию выпилили якобы языки высокого уровня не должны так много знать, в большинстве случаев это загоняют в статические командные файлы линкёра чтобы прибить стек в микроконтроллере, но для систем более высокого уровня всё-таки должны быть инструменты на уровне языка а не стандарта, регламентирующего костыли и аддоны.

на уровне языка очень дорого это оптимизировать, банально создать виртуальный стек и отладить агрессивную оптимизацию с сохранением стека - это реально боль, альтернатива в С++ это стек процессора, наверно

ну кстати я тут начал Раст изучать, да-да знаю, что разные языки, но с кешем пока не встретил проблем, когда в С например надо буквально мыслить как указатель например

Я бы поступил проще - добавить к любому статическому объекту атрибут. Ну как 0xABC... тоже самое что ABC.hex равно как 0b10 = 10.bin, побольше синтаксического сахара где он уместен. То есть количество информации небольшое, но оно легко парсится, достойно скармливается ИИ, так как влезает в контекстное окно и много других плюшек. Что то типа void f(void) {}.stack = {придумайте атрибуты настроек}; вполне себе укладывается в синтаксис. Раст - это надстройка над С, как С++ над ним же. По сути любую прогу из Раст можно транслировать на С со всеми плюшками. Если посмотрите ассемблерный выход то там ничего кроме ++/-- счётчиков-флажков и проверок указателей / переменных в стеке больше и нет. Шума много, а по сути маловато. Поэтому язык что то вяло продвигается чтобы стать стандартом ISO/IEC/ANSI.

"Если посмотрите ассемблерный выход то там ничего кроме ++/-- счётчиков-флажков и проверок указателей / переменных в стеке больше и нет. "

Если вкратце Rust вам не даст собрать чушь (без unsafe), он прямо скажет в чём проблема, и не даст никакого ассемблерного выхода, куда вы смотреть собрались, он научит правильно мыслить, а плюсы - приватное виртуальное наследование? исключение из исключения? Use after free? Конечно, дорогой, вот тебе бинарничек, используй на здоровье

Насколько я знаю, переполнение стека не входит в обеспечение гарантий безопасной работы с памятью в Rust, и в нем стек может переполниться как и в С++ не зависимо от safe или unsafe блоков.

Мне кажется, решаемвя проблема не особо актуальна.

Для обычной разработки переполнение стека я видел еще под Дос16.

А для эмбеда и Плк применяются другие технологии, исключающие проблему в принципе.

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

Рекурсия, понятно, запрещена.

В остальных случаях строится граф вызовов с известным размером стека.

Каким образом это можно сделать в случае, когда граф вызовов зависит от входных данных или от создаваемых динамически в рантайме?

Всегда есть максимальный путь

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

Все просто.

  1. Вычисляем максимально возможную глубину стека согласно графу вызовов программы. Автоматически, при компиляции программы.

  2. Устанавливаем размер стека

    Ничего избегать не нужно и бесполезно =)

Ну вообще в микроконтроллерах переполнение стека - очень распространенная проблема, особенно при использовании RTOS. И гарантированного способа отловить эту проблему до того, как она случится, в общем случае, по-моему, нет.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации