Как использовать -fsplit-stack в большом проекте

Недавно я опубликовал вопрос о сегментации стека и повысить сопрограммы но похоже, что подход -fsplit-stack работает только с исходными файлами, скомпилированными с этим флагом, среда выполнения ломается, когда вы переходите к другой функции, которая не была скомпилирована с -fsplit-stack. За пример

Это подразумевает, что среда выполнения использует локальную технику функции для определения того, когда текущий стек был превышен. А не уловка «сигнал охранной страницы», когда на конце стека всегда есть защитная страница, которая подаст сигнал при записи или чтении, сообщая среде выполнения выделить новый кадр стека и перейти к нему.

Тогда какая польза от этого флага? Если я свяжусь с любой другой библиотекой, которая не была с этим построена, код сломается (даже libstdc ++ и libc), тогда как это люди используют практически в больших проектах?


Из чтения gcc wiki Что касается разделенных стеков, то кажется, что вызов функции без разделенного стека из функции разделенного стека приводит к выделению кадра стека размером 64 КБ. Хорошо.

Но кажется, что вызов функции неразделенного стека из указателя функции еще не реализован в соответствии с приведенной выше схемой.

Какая польза от этого флага? Если я продолжу вызывать какую-либо виртуальную функцию, моя программа сломается?

Дальше от ответ ниже Похоже, в Clang не реализованы разделенные стеки?

8

Решение

Вы должны скомпилировать boost (по крайней мере boost.context и boost.coroutine) с поддержкой сегментированных стеков И вашего приложения.

  • скомпилируйте boost (boost.context и boost.coroutine) со свойством b2 segmented-stacks = on (включает специальный код внутри boost.coroutine и boost.context).

  • Ваше приложение должно быть скомпилировано с -DBOOST_USE_SEGMENTED_STACKS и -fsplit-stack (требуется заголовками boost.coroutines).

увидеть техническая документация

boost.coroutine содержит пример, демонстрирующий сегментированные стеки (в каталоге coroutine / example / asymmetric / call b2 toolset = gcc segmented-stacks = on).

относительно вашего последнего вопроса GCC Wiki заявляет:

Для вызовов из кода с разделенным стеком в код без разделенного стека компоновщик
изменит начальные инструкции в split-stack (вызывающем)
функция. Это означает, что компоновщик должен иметь специальные
знание инструкций, которые выдает компилятор. Эффект
изменения будут увеличивать необходимый размер кадра на число
достаточно большой, чтобы разумно работать на стек без разделения. Это будет
целевой номер; по умолчанию будет что-то вроде 64K. Заметка
что этот большой стек будет освобожден, когда функция разделения стека
возвращается. Обратите внимание, что я игнорирую случай кода с разделенным стеком в
разделяемая библиотека, вызывающая код без разделения стека в главном исполняемом файле;
это кажется маловероятной проблемой.

пожалуйста, обратите внимание: пока llvm поддерживает сегментированные стеки, лягушатые швы не обеспечивают __splitstack_<xyz> функции.

2

Другие решения

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

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

Обратите внимание, что похожие проблемы существуют с флагами, такими как -fno-exceptions и -fno-rtti. Обычно C ++ требует компиляции всего, что входит в исполняемый файл с совместимым набором флагов. Иногда можно смешивать и сочетать, но это часто хрупко. Это часть мотивации строительства все из источника и герметичных инструментов для сборки, таких как Bazel. Другие языки имеют разные подходы к не исходным компонентам, особенно к языкам на основе виртуальных машин, таким как Java и семейство .NET. В этих мирах такие вещи, как разделенные стеки, решаются на более низком уровне компиляции, но обычно никто не будет иметь никакого контроля или осведомленности о них на уровне исходного кода.

0

По вопросам рекламы [email protected]