Определение стекового пространства с Visual Studio

Для безопасной альтернативы попробуйте эти Перспективное дополнение Firefox

, Если эта ссылка не работает, пробуют этого: https://addons.mozilla.org/en-US/firefox/addon/perspectives /

7
задан Community 23 May 2017 в 11:46
поделиться

4 ответа

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

Следовательно, вам нужен ответ, где размещена страница gaurd. Но метод, который вы предлагаете, затронет рассматриваемую страницу и в результате сделает недействительным то, что вы пытаетесь измерить.

Неинвазивный способ определить, имеет ли страница (стек) защитный бит, - через VirtualQuery () .

1
ответ дан 6 December 2019 в 08:15
поделиться

Windows не выделяет память стека немедленно; вместо этого он резервирует для него адресное пространство и фиксирует его постранично при обращении к нему. Прочтите эту страницу для получения дополнительной информации.

В результате адресное пространство стека состоит из трех смежных областей:

  • Зарезервированная, но незафиксированная память, которая может использоваться для увеличения стека (но еще не была доступна) ;
  • Защитная страница, к которой еще не обращались, и которая служит для запуска роста стека при доступе;
  • Выделенная память, то есть память стека, к которой когда-либо обращался поток.

Это позволяет нам создать функцию. который получает размер стека (с детализацией размера страницы):

static size_t GetStackUsage()
{
    MEMORY_BASIC_INFORMATION mbi;
    VirtualQuery(&mbi, &mbi, sizeof(mbi));
    // now mbi.AllocationBase = reserved stack memory base address

    VirtualQuery(mbi.AllocationBase, &mbi, sizeof(mbi));
    // now (mbi.BaseAddress, mbi.RegionSize) describe reserved (uncommitted) portion of the stack
    // skip it

    VirtualQuery((char*)mbi.BaseAddress + mbi.RegionSize, &mbi, sizeof(mbi));
    // now (mbi.BaseAddress, mbi.RegionSize) describe the guard page
    // skip it

    VirtualQuery((char*)mbi.BaseAddress + mbi.RegionSize, &mbi, sizeof(mbi));
    // now (mbi.BaseAddress, mbi.RegionSize) describe the committed (i.e. accessed) portion of the stack

    return mbi.RegionSize;
}

Одна вещь, которую следует учитывать: CreateThread позволяет указать начальный размер фиксации стека (через параметр dwStackSize , когда флаг STACK_SIZE_PARAM_IS_A_RESERVATION не установлен). Если этот параметр не равен нулю, наша функция вернет правильное значение только тогда, когда использование стека станет больше, чем значение dwStackSize .

15
ответ дан 6 December 2019 в 08:15
поделиться

Вы можете использовать информацию в блоке информации о потоке Win32

Если вы хотите в потоке узнать, сколько места в стеке он использует, вы можете сделать что-то вроде этого:

#include <windows.h>
#include <winnt.h>
#include <intrin.h>

inline NT_TIB* getTib()
{
    return (NT_TIB*)__readfsdword( 0x18 );
}
inline size_t get_allocated_stack_size()
{
    return (size_t)getTib()->StackBase - (size_t)getTib()->StackLimit;
}

void somewhere_in_your_thread()
{
    // ...
    size_t sp_value = 0;
    _asm { mov [sp_value], esp }
    size_t used_stack_size = (size_t)getTib()->StackBase - sp_value;

    printf("Number of bytes on stack used by this thread: %u\n", 
           used_stack_size);
    printf("Number of allocated bytes on stack for this thread : %u\n",
           get_allocated_stack_size());    
    // ...
}
7
ответ дан 6 December 2019 в 08:15
поделиться

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

-1
ответ дан 6 December 2019 в 08:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: