47844


表題の通り、windows visual studio 2015 c++ でスレッドのスタックサイズの取得方法を教えていただきたく質問しました。  
具体的には_beginthreadex()で生成したスレッドのスタックサイズを取得する方法が知りたいです。マニュアルやＷＥＢを検索してみると、以下のメソッド群を利用することで取得可能なようですが、使い方が分からず困っています。

  * GetThreadContext();
  * GetThreadSelectorEntry();
  * ReadProcessMemory();

以上、宜しくお願い致します。


CC BY-SA 4.0
2018-08-27T04:46:44.453
47840
2018-08-28T11:51:21.507
2018-08-28T11:51:21.507
19110
13909
question
c++ windows visual-studio
windows visual studio 2015 C++ でスレッドのスタックサイズを取得する方法


公式ドキュメントの[Thread Stack Size](https://docs.microsoft.com/en-
us/windows/desktop/procthread/thread-stack-
size)によると、動作中のスレッドのスタックサイズを取得する方法については説明されていません。目的にも依りますが、あまり知るべきではないのかもしれません。もちろんデバッグ情報等を辿れば取得できるとは思います。

なお、スタックサイズはスレッド作成時に指定しますが、未指定時のデフォルト値は.EXEファイル作成時に[LINK.EXEの/STACKオプション](https://docs.microsoft.com/en-
us/cpp/build/reference/stack-stack-
allocations)で指定されいます。更に/STACKオプション未指定時のデフォルトは1MBとなっています。.EXEファイルに記録されているデフォルトのスタックサイズは[DUMPBIN.EXEの/HEADERSオプション](https://docs.microsoft.com/ja-
jp/cpp/build/reference/headers)で確認することができます。

* * *

> _beginthreadex() に指定したスタックサイズでスレッドが生成されているか確認したかった

質問文に書かれている通りですね。従来CreateToolhelp32Snapshotを含む[Tool Help
Library](https://docs.microsoft.com/en-us/windows/desktop/ToolHelp/tool-help-
library)ではスタックサイズは取得できませんでした。Windows 8以降には新たに[Process
Snapshotting](https://docs.microsoft.com/en-us/previous-
versions/windows/desktop/proc_snap/process-snapshotting-
portal)というライブラリが追加されており、これを使用することで[TEB構造体](https://docs.microsoft.com/en-
us/windows/desktop/api/winternl/ns-winternl-
_teb)が得られます。TEB構造体がundocumentedながらスタックサイズが含まれていますので、これらを駆使することで得られます。参考までにコードを書いてみました。  
このAPIはググっても使用例が出てきませんね。

[code]

    #include <chrono>
    #include <thread>
    #include <process.h>
    #include <Windows.h>
    #include <winternl.h>
    #include <ProcessSnapshot.h>
    using namespace std::literals;
    
    int main() {
        unsigned tid;
        auto thread = (HANDLE)_beginthreadex(nullptr, 128 * 1024, [](auto) -> unsigned {
            std::this_thread::sleep_for(10s);
            return 0;
        }, nullptr, 0, &tid);
        CloseHandle(thread);
        printf("_beginthreadex(): created thread id: %u\n", tid);
    
        printf("dump all stack sizes.\n");
        HPSS snapshot;
        PssCaptureSnapshot(GetCurrentProcess(), PSS_CAPTURE_THREADS, CONTEXT_ALL, &snapshot);
        HPSSWALK walk;
        PssWalkMarkerCreate(nullptr, &walk);
        for (PSS_THREAD_ENTRY te; PssWalkSnapshot(snapshot, PSS_WALK_THREADS, walk, &te, sizeof te) == ERROR_SUCCESS;) {
            auto teb = reinterpret_cast<const TEB*>(te.TebBaseAddress);
            auto stack_size = static_cast<const char*>(teb->Reserved1[1]) - static_cast<const char*>(teb->Reserved1[2]);
            printf(" tid: % 5u, % 7lldbytes\n", te.ThreadId, stack_size);
        }
        PssFreeSnapshot(GetCurrentProcess(), snapshot);
        return 0;
    }
    
[/code]


CC BY-SA 4.0
2018-08-27T06:23:03.870
47844
2018-08-28T07:55:28.180
2018-08-28T07:55:28.180
4236
4236
47840
answer