How can we poll the state of the stack - unused (available) memory

How can we get this information? I think it depends on the OS, and I am running Windows, so my question relates to the windows API.

Is there any function that can do this for us - to get the remaining memory stack for the calling thread?

Alternatively, if we could find out the following details, we can figure it out on our own:

  • Get the base address of the stack stack. There should be some function that takes the stream identifier as a parameter and returns some information about it (for example ... Base stack address?)
  • Get thread stack size. If the thread was started by us, we can know this (since we indicated it when calling CreateThread). But if this is the main thread that the OS launched for our program or some other thread, we did not start explicitly, how do we find it?
  • Get the current stack pointer. Well, that is easier. we can either check it with esp, or take the address of a local variable to get a private location.

This is for educational purposes, but I suggest that it can be used to stop the recursive algorithm from - instead of using any function to limit the maximum depth.

+5
source share
4 answers

NtCurrentTeb(), TEB. NT_TIB :

typedef struct _NT_TIB
{
     PEXCEPTION_REGISTRATION_RECORD ExceptionList;
     PVOID StackBase;
     PVOID StackLimit;
     PVOID SubSystemTib;
     // ....
} NT_TIB, *PNT_TIB;
+5

OP, , : "... , - ".

API Windows SetThreadStackGuarantee(), , . VC _resetstkoflw() .

. this MSDN.

+1
  • : wj32 , StackBase .

  • . ( ) . StackLimit, , , - , . , , CreateThread, - , , STACK_SIZE_PARAM_IS_A_RESERVATION. linker 1MB, . , , 1 .

    stack - , StackPage VirtualQuery, gaurd, . , , , .

  • : StackLimit, , , . esp, , StackLimit.

vs commited. Windows , - . . , . Windows - - () .

Edit

gaurd . , ​​ , . , VirtualQuery AllocationBase , . :

#include <windows.h>
#include <WinNT.h>
#include <stdio.h>

DWORD GetThreadStackSize()
{
    SYSTEM_INFO systemInfo = {0};
    GetSystemInfo(&systemInfo);

    NT_TIB *tib = (NT_TIB*)NtCurrentTeb();
    DWORD_PTR stackBase = (DWORD_PTR)tib->StackBase;

    MEMORY_BASIC_INFORMATION mbi = {0};
    if (VirtualQuery((LPCVOID)(stackBase - systemInfo.dwPageSize), &mbi, sizeof(MEMORY_BASIC_INFORMATION)) != 0)
    {
        DWORD_PTR allocationStart = (DWORD_PTR)mbi.AllocationBase;
        return stackBase - allocationStart;
    }
    return 0;
}

DWORD WINAPI ThreadRtn(LPVOID param)
{
    DWORD stackSize = GetThreadStackSize();
    printf("%d\n", stackSize);
    return 0;
}

int main()
{
    ThreadRtn(NULL);
    HANDLE thread1 = CreateThread(NULL, 65535, ThreadRtn, NULL, 0, NULL);
    WaitForSingleObject(thread1, -1);
    HANDLE thread2 = CreateThread(NULL, 65535, ThreadRtn, NULL, STACK_SIZE_PARAM_IS_A_RESERVATION, NULL);
    WaitForSingleObject(thread2, -1);

    return 0;
}

:

1048576 1048576 65536

.

+1

edit: This is a great question for educational purposes! Have an upvote for this. The stack space is fixed by edit: at the point when a process or thread begins execution; I think you should understand the heap from which memory is dynamically allocated (e.g. malloc ()). This question is well discussed here on MSDN . I don’t see the exact API call you are looking for: you have to do this, it cannot be too far.

Hth

-1
source

All Articles