Минимально возможный размер стека в Windows при использовании исключений C ++ (с использованием улучшенных контекстных волокон)

Я использую Boost Context 1.67 для создания волокна (fcontext API)
с минимально возможным размером стека в Windows 10.

Вероятно, эта проблема касается не только повышения контекста, но и любого сценария, в котором мы используем поток Windows с минимальным размером стека.

Я столкнулся с проблемами при использовании очень маленьких стеков (до 10 Кб)
через исключения stackoverflow, которые вызваны внутренним
исключение стека разматывания, выданное контекстом повышения, как показано ниже:

введите описание изображения здесь

При использовании большего стека (> 10 кб) я не сталкиваюсь с какими-либо проблемами.

Для воспроизведения достаточно следующего примера:

#include <memory>
#include <utility>
#include <boost/context/all.hpp>

#define STACK_SIZE 8000

struct my_allocator
{
boost::context::stack_context allocate()
{
void* memory = std::malloc(STACK_SIZE);
return {STACK_SIZE,
static_cast<char*>(memory) +
STACK_SIZE};
}

void deallocate(
boost::context::stack_context& context)
{
std::free(static_cast<char*>(context.sp) -
STACK_SIZE);
}
};

int main(int, char**)
{
boost::context::fiber fiber(
std::allocator_arg, my_allocator{},
[](boost::context::fiber&& sink) mutable {
// ...
return std::move(sink);
});

// Will cause a stack unwind exception and
// reproduces the issue
return 0;
}

Усиление контекста здесь используется только для выполнения переключения контекста с выделенным пользователем стеком, вероятно, проблема вызвана некоторыми ограничениями исключений MSVC C ++, которые, вероятно, требуют определенного минимального размера стека для работы. Так же SetThreadStackGuarantee Функция WinAPI не оказывает никакого влияния на проблему.

Стек выделяется через malloc, как показано в примере.

Можно ли использовать в Windows стеки меньшего размера, чем 10 КБ, при использовании исключений C ++? Какие обстоятельства могут быть причиной ограничения здесь?

2

Решение

К сожалению, Windows API не предоставляет функцию или константу, возвращающую минимально необходимое пространство стека.

Только на 32-битных Windows исключения (SEH) вызывают записи в стеке.
В Win x64 используется обработка исключений на основе таблиц — записи для обработчиков исключений хранятся в разделе pdata.
Так что обработка исключений на x64 не должна влиять на мин. пространство стека.
Соглашение о вызовах x64 требует некоторого пространства — например, 32 байта «теневого пространства» + пространство для регистров XMM … но для хранения регистров требуется всего несколько байтов.

Я думаю, что мин. пространство стека ограничено «кодом инструментария» (например, файлы cookie стека и т. д.) — возможно, это может контролироваться флагами компилятора.

boost.context выделяет память и использует ее в качестве стека (+ реализует переключение контекста).
boost.fiber использует стек из boost.context и резервирует пространство (размещение нового) для структуры управления в верхней части стека каждого волокна (но это < 1kB).

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

1

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

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector