Version 8.02
インスタンスハンドル
「今回も引き続き、 WinMain() 関数について見ていきます」
『一番最初に呼ばれる関数なんだよね。こういう』
int WINAPI WinMain
( HINSTANCE p_hInstance
, HINSTANCE p_hPrevInstance
, LPSTR p_pchCmdLine
, int p_iCmdShow
)
『引数と戻り値で』
「そう。で、前回は WINAPI っていうのの説明だけしました」
『ってことは今回は引数ね』
「そう、今回はその中でも重要な【インスタンスハンドル】っていうものに
ついて解説します」
『いんすたんすはんどる……いんすたんすのハンドルなんだろうけど、イン
スタンスって?』
「英語で instance 、〈実体〉って意味があります」
『実体、ねぇ』
「この用語、実はいろんな場面で使われるから、注意してね。とりあえず
は【インスタンスハンドル】って【ハンドル】まで付けちゃえば、他と間違
えることはないかな」
『んー、でもウィンドウハンドルみたく、なんかのハンドルではあるんだよ
ね』
「そう、インスタンスのハンドル」
『そのまんま。そのインスタンスはなんなの?』
「アプリの実体、っていうのが一番正しいんだけど……」
『歯切れ悪いわねー』
「たとえば今回の SimpleDialog.exe 」
『これがアプリよね』
「正確に言えば実行ファイル、かな」
『実行するファイルね』
「アプリケーションっていうのは実行ファイルの他にいろんなファイルも
くっつけてまとめてパッケージに入れてお店で売ってるの、かな」
『なんか細かいね』
「結構この辺って色々あってね……で、この実行ファイルをダブルクリック
すれば実行できます。でも、これは実体じゃないんです」
『どゆこと?』
「これはファイル。ハードディスクに置かれたファイルで、これだけだとど
うやっても実行できないんです」
『でもダブルクリックしたら実行できるじゃない』
「つまりダブルクリックしたら〈実行できる形〉にしてくれるんです」
『あ、そしたら実行できる!』
「そゆこと。この〈実行できる形〉っていうのは、このファイルがメモリに
置かれた状態もののことなんです」
『メモリの上?』
「メモリの上。ハードディスクの上の情報を、メモリの上にコピーしたら、
やっと実行できる状態になるんです」
『複雑ねぇ……あ、それでインスタンスって?』
「インスタンスは、このメモリ上に置かれたファイルのこと」
『そっか、実行できるこっちの方が実体になるんだ!』
「このメモリ上に置かれてやっと、ウィンドウズはこの実行ファイルの中の
プログラムを読んで、実行してくれるんです」
『なんか複雑ね』
「まぁ、たとえて言うなら、人間が本を読む時も同じかな」
『……本の複製は作んないじゃん』
「でも、本の内容は一度頭の中に入れるでしょ」
『頭の中って脳のこと? そっか、それがメモリなんだ』
「そゆこと。……余計ややこしくなっちゃったかな」
『ようするにファイルをメモリに置かないとダメってことね』
「ま、それはそういうこと。じゃあそれを実際に見てみます」
int WINAPI WinMain
( HINSTANCE p_hInstance
, HINSTANCE p_hPrevInstance
, LPSTR p_pchCmdLine
, int p_iCmdShow
)
{
MessageBox( NULL, "テスト", "WinMain()", MB_OK );
return 0; // ここにブレークポイント。
}
「指定したとこにブレークポイント置いて」
『手袋マークっと。実行してダイアログ出て閉じて止まるっと』
「まず、プログラムがメモリに置かれてるってのを見た方がいい
かな。【混合モード】って憶えてる?」
『 Version 6.08 ( No.108 ) でやったね。あ! ここでも〈プログラムの
置かれたアドレス〉って言ってる!』
「そう、つまり実行ファイルがメモリ上に置かれてて、だからそのアドレス
もちゃんとあるわけ」
『ってことは、変数なんかと同じとこにあるの?』
「それを見るためには?」
『ポインタの時に使ったメモリウィンドウ!』
「そゆこと。 Version 4.02 ( No.052 ) を参照ってことで……っとその前
に、その混合モードのとこ」
13: return 0;
0040D775 33 C0 xor eax,eax
14: }
「これの見方をまず簡単に教えておくね」
13: return 0;
『これはただのコードだよね』
「そう、このコードの下にある1行が、コンパイルして実行されてメモリに
置かれたものそのもの」
『左端がアドレスね。それはわかるんだけど……』
「その右の 33 C0 は、コンピューター専用の言葉。この言葉を【機械語】
とか【マシン語】って言います」
『機械の言葉だから機械語ね』
「昔の人は、これを直接書いてプログラム作ってたらしいよ」
『げ! 信じらんない!』
「ま、それに近いことは今でもしたり」
『げげ』
「それに使うのが、右の xor とか。これは【アセンブラ言語】っていうも
の」
『お、ちょっとプログラミングっぽいね』
「って言っても、これは左側の数字をただちょっと分かりやすい単語に置き
換えただけなんだけどね」
『っつーか xor ってなんかよく分かんない……』
「このアセンブラは、実は C++ 言語のプログラムの中に普通に書くことが
できるんです」
『! ってことはいつかこれ教えられるの!?』
「いや、僕もちょっとこれは苦手……」
『ほっ』
「と、その辺はとりあえず本題とは違うので置いときます。ここで重要なの
はアドレス。じゃあ、このアドレスをメモリウィンドウで見てみて」
『ほい。メモリウィンドウを出して、上の【アドレス】にこのアドレス
を……』
「 Ctrl+c でコピー、 Ctrl+v で貼り付けられるから」
『おお。んでリターン』
0040D775 33 C0 5F 5E 5B 83 C4 40 3B EC E8 7C 39 FF FF 8B E5 5D C2 10
『おおっ、 33 C0 が同じ!』
「ここで重要なのは、これがメモリウィンドウだってこと」
『……何バカ言ってるの、当たり前じゃない』
「これで、ポインタの時は何を見た?」
『変数の中身……あ! 変数と、プログラム、同じとこに置かれてる!!』
「そうなんです。つまり、メモリにアクセスできるってことは、プログラム
そのものにもアクセスできるってことなんです」
『……結構危険ね……』
「うん、危険。こういうとこしっかり知っておかないと、これから本当にま
ずいプログラム書きかねないから」
『なんか真面目……』
「実際、これまでと今回からってちょっと違うかも」
『重さが違う〜』
「で、話を元に戻して、インスタンスハンドル」
『そうそう、それそれ』
「まずはっきり言っちゃえば、ハンドルはポインタと同じ」
『前に聞いたような……』
「うん、少しずつ言ってはいたからね。で、ハンドルがポインタと同じって
ことは、ハンドルはアドレス、ってことはインスタンスハンドルはインスタ
ンスのアドレス」
『ってことはプログラムそのもののアドレス!』
「そゆこと。というわけで見てみましょう。今度は変数ウィンドウを開い
て」
『今回はデバッグウィンドウ使いまくりね。ほい。あ、インスタンスハンド
ル見るの?』
「そう、ローカルで p_hInstance を見てみて。いくつになってる?」
『16進数で 0x00400000 だよ。これをメモリウィンドウで見る!』
00400000 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00 B8 00 00 00
『……やや意味不明な感じが……』
「実は、前にもこれと似たようなのを見たことがあるんだよねー」
『げ、そう?』
「ま、かなり昔だから忘れちゃったと思うけど。 Version 1.0 ( No.003 )
を見て」
『うわ、昔すぎ! 見たくない!』
「まぁ見なくてもいいかも……この時と同じように、 SimpleDialog.exe を
バイナリーファイルとして開いてみて」
『ほいほい。なんか不思議な感じ……とりゃ』
000000 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00
『お! 同じだ! ってことは、メモリの上に実行ファイルがそのまんま置
かれてる!』
「ま、そのままってわけじゃないけどね」
『あ、ホントだちょっと違う』
「でもほとんど同じと思っていいかな。こういうふうに、実行ファイルはメ
モリ上に置かれます。で!」
『で? あ、インスタンスハンドル!』
「そう、インスタンスハンドルは 0x00400000 、このアドレスから実行ファ
イルが置かれてます」
『メモリウィンドウは、その上だと ?? になっちゃってるね』
「つまり、このインスタンスハンドルは、メモリ上のどこから実行ファイル
が置かれてるか、ってこと示すアドレスのことなんです」
『おおお! つまりそのプログラムの、メモリ上の最初のとこってことね』
「簡単に言えばそういうこと」
『……で?』
「で、 Version 3.6 ( No.031 ) でちょっとやったけど、 LoadIcon() って
API を使う時に」
『インスタンスハンドル渡してるね』
「 LoadIcon() は、実行ファイルの中に埋め込まれてるアイコンを使える状
態にする API 。この関数にインスタンスハンドルを渡すのは、プログラム
の最初が分からないといけないから」
『そのためにインスタンスハンドルが必要なのねー』
「 API ではこういうことくらいしかインスタンスハンドルを使いません。
だから、実はインスタンスハンドルって特に重要じゃないんです」
『アドレスも、なんかすごく切りのいい数字だし、あんま重要じゃないの
ね』
「が!」
『が?』
「というわけで次回に続く」
/*
Preview Next Story!
*/
『またメモリウィンドウ大活躍ね〜』
「これは大きいんだよ。他のだとこういうのついてないから」
『他のって?』
「 gcc とか bcc とか、タダのがあるんだよね」
『 VC っていくらくらい?』
「結構するかな。でも、特に初心者はデバッグ環境が重要!」
『そのひとつがこのメモリウィンドウなわけね』
「というわけで次回」
< Version 8.03 インスタンスとメモリ >
『につづく!』
「というわけで、あと2回くらいメモリウィンドウ使います」
『ケチくさ!』