最近ヒマさえあればChatGPTとおしゃべりしてます、ズモモです。
この記事もそうなんだけど、こうやってChatGPTと話した内容をqiitaの記事としてメモするの結構良いかもしれないな。意識的にやっていきたい。
。。。。
本題に入ります。
C言語入門本でDXライブラリを使おうとしてでてきたHINSTANCEのHってなーあに?っていうところから、そもそもハンドルって何なのか、実際に動いているプロセスのハンドル番号を確認してみよう!という流れになりました。
というわけで、コンソールウィンドウのハンドル番号を取得して表示するプログラムを(ChatGPTが)作ったぞい!
#include <windows.h>
#include <stdio.h>
int main() {
HWND hwnd = GetConsoleWindow(); // コンソールウィンドウのハンドルを取得
if (hwnd != NULL) {
printf("Console Window Handle: %p\n", hwnd);
}
else {
printf("Failed to get handle\n");
}
getchar(); // exe実行時画面がすぐに閉じないようにするため
return 0;
}
- GetConsoleWindow() は、今動いてるプログラムのコンソールウィンドウのハンドルを取得してくれる
- ハンドルはポインタ型みたいに見えるけど、中身は単なる番号やID
- printfで値を出すと、「これがハンドルのIDね」ってのが表示される
Console Window Handle: 00000000002609F4
ハンドル(上の実行例だと00000000002609F4
)は8バイトの16進数(64bit環境)。
うーん、やっぱぱっと見ポインタっぽい?
ハンドル見れた~(だから何)!?ですでに満足してはいるけど、以下ChatGPT君の詳しい説明です。
Windowsのハンドルってどーいう形式?
俺:そもそもWindowsのウィンドウハンドルって16進数の8バイトで管理されてるの?
ChatGPT君:
おお、そこに目をつけるのは鋭いな!じゃあ、ちょっと詳しく説明していくね。Windowsのウィンドウハンドル (HWND) のサイズ
Windowsのウィンドウハンドル(HWND)は、内部的には 「ポインタ」 として扱われているんだけど、実際の仕様としては ハンドル型 (HANDLE) という独自の型で管理されているんだ。これが16進数で表示されるのは、値がメモリ上のアドレスのような振る舞いをしているから。
さて、「何バイトで管理されているか」 の話だけど、これは システムのアーキテクチャ によって決まるんだ。
32ビットOS:ハンドルは 4バイト(32ビット)
64ビットOS:ハンドルは 8バイト(64ビット)
つまり、質問に対する答えは:はい、64ビットOSではウィンドウハンドルは16進数の8バイトで管理されている。
ハンドルの実体
ただし、ハンドルの値そのものは、常にメモリアドレスを直接指しているわけではない。Windowsの内部で、ハンドルは カーネルが管理するオブジェクトの「ID」または「インデックス」 のようなものとして扱われていて、実際のメモリアドレスではなく、間接的な参照に使われることもあるんだ。
この設計により、ハンドルを外部に公開しつつも、Windowsの内部構造を直接触らせないような仕組みになっている。
なぜ16進数で表示されるのか
00000000002609F4 のような16進数で表示される理由は、ハンドルの値がメモリアドレスっぽい振る舞いをするからだ。16進数で表現するとメモリの内容を人間が直感的に理解しやすくなるので、デバッグなどではこの形式が一般的に採用されている。こんな感じで、64ビット環境ではハンドルは確かに 8バイトの16進数 で管理されている。納得できたかな?
そもそもポインタも全然わからねえ。
とりあえずハンドルっていう番号でウィンドウを管理してるってのはわかった。
(おまけ)ハンドルとポインタの違い
特徴 | ハンドル | ポインタ |
---|---|---|
用途 | リソースを指し示す「管理番号」 | メモリ上の「データの住所」 |
管理者 | OSやシステムが管理 | プログラマが直接操作 |
安全性 | システムが管理してるから安全 | メモリ操作をミスるとクラッシュの可能性あり |
確認方法 | デバッグやAPIで値を見る | 直接操作・デリファレンス可能 |
カンケーないけどポインタ操作してどこまでメモリをぶっ壊せるのか(そしてだからといってどうなるのか)、ちょっと試してみたいわね。ってポインタという概念を知ってからずっと思っているのでそのうちやってみたいです。パソコン壊れない程度に。
(おまけ2)WindowsアプリのインスタンスとJavaとかオブジェクト指向で出てくるクラスのインスタンスの違い
インスタンスってJavaとかC++とかオブジェクト指向で出てくる言葉のイメージだったので、C言語の型にインスタンスって出てきたときは「おっ」と思いました。違いを表にまとめてみます。
比較項目 | Java / C++ の インスタンス | Windows の インスタンス |
---|---|---|
定義 | クラス(オブジェクト指向)のインスタンス。 | クラスから生成された具体的なオブジェクト。 |
作成方法 | newキーワードを使ってオブジェクトを生成する。 | アプリケーションが起動したときにOSが作成。 |
管理 | メモリ上のオブジェクトとして管理され、ガベージコレクションやポインタで管理される。 | OSやウィンドウマネージャが管理。 |
関連する用語 | オブジェクト、ポインタ、クラス、メソッド。 | プロセス、ウィンドウ、タスクマネージャ。 |
役割 | クラス定義に基づいて状態や振る舞いを持つ。 | アプリケーションが実行されている状態を指す。 |
例 | Person p = new Person();で作ったオブジェクト。 | 同じアプリを2回起動するときの2つ目の実行インスタンス。 |
ライフサイクル | プログラムがオブジェクトを作成し、必要がなくなるとGC(ガベージコレクション)で解放される。 | OSが終了するまでプロセスとして実行され続ける。 |