Доступный размер стека для потока C++

Использую Windows 10, Visual Studio 2019 Программа генерирует потоки. Мне нужно добавить функциональность, указывающую мне, какой размер стека доступен в любое время выполнения.

#include <iostream>
#include <thread>

void thread_function()
{
    //AvailableStackSize()?  
    //Code1 //varibales on stack allocation + function call
    //AvailableStackSize()? it should decrease
    //Code2 //varibales on stack allocation + function call
    //AvailableStackSize()? it should decrease
    //Code3 //varibales on stack allocation + function call
    //AvailableStackSize()? it should decrease
}

int main()
{
    std::thread t(&thread;_function);
    std::cout << "main thread\n";
    std::thread t2 = t;

    t2.join();

    return 0;
}

Я пытаюсь использовать. Но я не знаю, как мне продолжить. Я просто могу узнать, каков общий размер стека. Недоступный.

bool AvailableStackSize()
{
    // Get the stack pointer
    PBYTE pEsp;
    _asm {
        mov pEsp, esp
    };

    // Query the accessible stack region
    MEMORY_BASIC_INFORMATION mbi;
    VERIFY(VirtualQuery(pEsp, &mbi, sizeof(mbi)));

    return mbi.RegionSize;//This is a total size! what is an available? Where guard is located?

}

Возможно, я также могу проверить, есть ли какой-либо адрес внутри стека

PVOID add;
(add>= mbi.BaseAddress) && (add < PBYTE(mbi.BaseAddress) + mbi.RegionSize);

Я видел несколько подобных вопросов, но на 100% никто не отвечает. Как правильно получить доступный размер стека?

1 ответ

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

__declspec(noinline) size_t AvailableStackSize()
{
    // Query the accessible stack region
    MEMORY_BASIC_INFORMATION mbi;
    VERIFY(VirtualQuery(&mbi, &mbi, sizeof(mbi)));

    return uintptr_t(&mbi) - uintptr_t(mbi.AllocationBase);
}

Это будет немного отличаться от того, что фактически доступно в вызывающей программе, потому что при вызове функции использовались некоторые (для хранения адреса возврата и любых сохраненных регистров). И вам нужно будет выяснить, появляется ли последняя защитная страница в том жеVirtualQuery результат или соседний.

Но это общий подход.

Другие вопросы по тегам