Determinando el espacio de stack con Visual Studio

Estoy progtwigndo en C en Visual Studio 2005. Tengo un progtwig multiproceso, pero eso no es especialmente importante aquí.

¿Cómo puedo determinar (aproximadamente) cuánto espacio de stack usan mis hilos?

La técnica que estaba planeando usar es establecer la memoria de la stack en un valor predeterminado, digamos 0xDEADBEEF, ejecutando el progtwig por un largo tiempo, pausando el progtwig e investigando la stack.

¿Cómo leo y escribo la memoria de la stack con Visual Studio?

EDITAR: consulte, por ejemplo, “Cómo determinar el uso máximo de la stack”. Esa pregunta habla sobre un sistema integrado, pero aquí estoy tratando de determinar la respuesta en una PC normal.

Windows no compromete la memoria de stack inmediatamente; en su lugar, reserva el espacio de direcciones para él y lo compromete página por página cuando se accede a él. Lee esta página para más información.

Como resultado, el espacio de direcciones de la stack consta de tres regiones contiguas:

  • Memoria reservada pero no confirmada que se puede usar para el crecimiento de la stack (pero nunca se ha accedido aún);
  • Página de protección, a la que nunca se ha accedido todavía, y sirve para activar el crecimiento de la stack cuando se accede a ella;
  • Memoria comprometida, es decir, memoria de stack a la que alguna vez tuvo acceso el hilo.

Esto nos permite construir una función que obtiene el tamaño de stack (con granularidad de tamaño de página):

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 (ie accessed) portion of the stack return mbi.RegionSize; } 

Una cosa para tener en cuenta: CreateThread permite especificar el tamaño de compromiso inicial de la stack (a través del parámetro dwStackSize , cuando el indicador STACK_SIZE_PARAM_IS_A_RESERVATION no está establecido). Si este parámetro no es cero, nuestra función devolverá el valor correcto solo cuando el uso de la stack sea mayor que el valor de dwStackSize .

Puede hacer uso de la información en el bloque de información de subprocesos Win32

Cuando desee en un hilo averiguar cuánto espacio de stack utiliza, puede hacer algo como esto:

 #include  #include  #include  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()); // ... } 

La stack tampoco funciona de la manera que esperas. La stack es una secuencia lineal de páginas, la última (arriba) una de las cuales está marcada con un bit de protección de página. Cuando se toca esta página, se retira la punta protectora y se puede usar la página. Para un mayor crecimiento, se asigna una nueva página de guardia.

Por lo tanto, la respuesta que desea es dónde se asigna la página gaurd. Pero la técnica que propones tocaría la página en cuestión y, como resultado, invalidaría lo que estás tratando de medir.

La forma no invasiva de determinar si una página (stack) tiene el bit de protección es a través de VirtualQuery() .

Puede usar la función GetThreadContext () para determinar el puntero de la stack actual del hilo. Luego use VirtualQuery () para encontrar la base de la stack para este puntero. Al sustraer esos dos indicadores, obtendrá el tamaño de la stack para un hilo dado.