#pragma twice

KAB-studio > プログラミング > #pragma twice > 319 Version 15.19 DLL をデバッグ!

#pragma twice 319 Version 15.19 DLL をデバッグ!

前のページへ 表紙・目次へ 次のページへ

 Version 15.19
DLL をデバッグ!

今回は、 DLL のデバッグについて説明します
 DLL のデバッグ?
そう、 DLL と Exe って分かれてるでしょ
あ……そういえばそうだよね。デバッグで実行、ってやっぱ Exe でする
んだろうけど、でもそしたら、 DLL のプログラムでブレークポイント掛け
たりするのってどうするんだろう……
今回はその辺を説明します。まず、基本的に、 DLL のデバッグは次の
2通りの方法があります

・ Exe 側のプロジェクトで実行して DLL のソースを参照する
・ DLL 側のプロジェクトから Exe を実行する

あれ!? DLL 側から Exe を実行できるの!?
できるんです。そういう事ができないと、特に DLL を修正するのが大変
でしょ
確かに…… DLL のプロジェクト開いて、そっちでデバッグしつつ修正で
きたらすごく楽そう
まぁそれは後回しにして、先に Exe の方から

・ Exe 側のプロジェクトで実行して DLL のソースを参照する

 Exe の方って事は、今やってるのだと BuildTest のプロジェクトだね
そう、まず BuildTest のプロジェクトを開いて。前回のそのままなら

// Main.cpp
#include <Windows.h>

#include "DLLTestHard.h"
#include "Func.h"

int WINAPI WinMain
    ( HINSTANCE p_hInstance
    , HINSTANCE p_hPrevInstance
    , LPSTR p_pchCmdLine
    , int p_iCmdShow
    )
{
    Output( "あいうえお\n" );

    return 0;
}

ってなってるはず
 DLLTestHard.dll の Output() 関数を呼んでるんだよね
というわけでその Output() の方に飛んでみましょう。 Output() を呼ん
でいる所にブレークポイントを置いて
……へ? いきなり?
そう、いきなり
……うん、ブレークポイント置いた
そこで止めて、ステップインしてみて
……何もやってないのにいきなり……えっ!? Func.cpp の Output() 
関数が出てきた!!
 DLLTestHard プロジェクトの Func.cpp が開いたでしょ
えーっ!? 嘘、こんなに簡単に!? じゃあ Exe からだと、 DLL って
簡単にデバッグできるんじゃない!
そう、実は簡単にデバッグできるんです
……なんで?
それは、 DLL には〈ソースファイルの場所〉を取得するための仕組みが
あるから
つまり、 DLLTestHard.dll が、 Output() が Func.cpp にある、ってい
う情報を持っている、ってこと?
うーん、ちょっと違うんだけど。情報そのものは持ってないんだけど、
情報を持ってるファイルの場所を知っている、ってことかな
???
まず、今話した〈デバッグのための情報を持っているファイル〉について
説明します
デバッグのための情報を持っているファイル……そのファイルに、どの
関数がどのソースファイルにある、っていう情報が入ってるわけね
そういうこと。これは拡張子が .pdb のファイル
あれ、結構見たことあるような
このファイルは、 Exe でも DLL でも作られるんです。たとえば 
BuildTest の場合、 BuildTest.pdb というファイルが作られます
あ、 BuildTest.exe と同じフォルダに置いてある
同じく、 DLLTestHard には DLLTestHard.pdb があります
ホントだあった!
このファイルに、どの関数がどのソースファイルに入っているか、といっ
た情報が入っているわけです
へー
だから、たとえば DLLTestHard.pdb を DLLTestHard.pdb___ にして、同
じようにステップインしてみて
ほい。あ、できない
 DLLTestHard.pdb を見つけられなかったから、そこからソースファイル
を参照できなくて
ステップインできなかったってわけねー
ちなみにこの .pdb ファイルは【プログラムデータベース】と言います
プログラムのデータベース、ねぇ
ってほどのものでもないんだけどね。デバッグ情報がメインだから。話を
戻すと、この .pdb ファイルを、実は DLL はフルパスで指定しています
フルパス!?
そう、 D:\Program\DLLTestHard\Debug\DLLTestHard.pdb みたいに、
フルパスの情報を DLL の中に持っているんです
だから Exe の方にコピーしても、ちゃんと DLLTestHard.pdb が見つけら
れる、ってこと?
そういうこと!  DLL の中に DLLTestHard.pdb のフルパスが書かれてい
るからこそ、 DLL をどこにコピーしてもちゃんとデバッグができるという
わけです
……ねぇ、それじゃ、 DLL のプロジェクトを移動したらデバッグできな
くない?
うん
……
それに、デバッグ機能も含めた DLL をインターネットで配布する時に
あ、それ困る! 使ってる人でプロジェクトなんて違うんだから
実は pdb ファイルは DLL の置いてあるフォルダと同じフォルダに置いて
おけばちゃんと見てくれるから大丈夫
あ、そうなんだ。ん? でもさ、ソースファイルの方がみつからなくな
い?
ソースファイルの方は、ちゃんとダイアログが出て、指定できるように
なっているんです。 Func.cpp を Func.cpp___ にして試してみて
ほい。あ、【ソース ファイルの検索】ってダイアログが出た!
これで Func.cpp の置いてあるフォルダを指定すればOK
こっちはちゃんと変えられるわけね
この二段構えだから、プロジェクトを移動したり、インターネットで配布
したりしても大丈夫
ちゃんと考えられてるんだね
さて、ここまでは Exe 側から使う方。次は DLL 側から

・ DLL 側のプロジェクトから Exe を実行する

なんとなく、こっちは大変そうな気がする……
さすがに Exe みたいに〈何もしないでできる〉ことはないけど、でも 
Exe くらい簡単だよ
え、そなの?
というわけで、 DLL 側から、今回の例だと DLLTestHard プロジェクト側
からデバッグする方法を見ていきます
はーい
まずは、実行する Exe を指定します。メニューの【プロジェクト】-
【設定】ダイアログを開いて
いつものダイアログね
【プロジェクトの設定】ダイアログの【デバッグ】-【一般】ページを開
いて、その【デバッグ セッションの実行可能ファイル】に、実行する Exe 
のフルパスを入力してください
ここに、 BuildTest.exe のフルパスを書けばいいの?
そういうこと。そうすると、この Exe を実行してデバッグができます
……もしかして、これだけ?
そう、これだけ。【OK】ボタンを押して閉じたら、 Func.cpp を開いて

// Func.cpp

#include <windows.h>
#include "DLLTestHard.h"
#include "Func.h"

// エクスポートする関数。
DLLTESTHARD_API void Output( const char *p_pch )
{
    OutputDebugString( p_pch );
}

この OutputDebugString() の行でブレークポイントを置いて
ほい
そうしたらデバッグ実行
……普通にデバッグ実行していいの?
そう、 Exe と同じようにしてみて
なんかドキドキする……えい。あ、ブレークポイントで止まった
 BuildTest.exe の方が実行されて、 WinMain() から呼び出されたんで

……ホントに?
というわけで、この状態でステップアウトするか、そのまま
ステップオーバーして進めてみて
関数から抜けるってわけね……あ!! BuildTest.cpp が表示されて、 
Output() 呼んでる所で止まった!!
つまり、 DLL のプロジェクトから、 Exe のデバッグができてる、ってこ

すごーい!! DLL の方から、普通に Exe のデバッグ実行してるみたい
な感じ!!
というかそのままだね。基本的に DLL だからとか Exe だから、っていう
区別はないし
でも、 DLL のプロジェクトからは Exe のパスしか指定してないのに、な
んでソースファイルまで開くの? ……あ、もしかして
そう、 .pdb ファイルがあるから。一度終了してから、 BuildTest.pdb 
を BuildTest.pdb___ に修正して、デバッグ実行してみて
 Exe の方の pdb ファイルを消しちゃうわけね。……あ、ダイアログが出

【'D:\……\BuildTest\Debugにはデバッグ情報がありません。続行する場
合は[OK]を押してください】っていうダイアログが出ます
 BuildTest.pdb が見つからないから?
そういうこと。 BuildTest.exe には BuildTest.pdb のフルパスが書かれ
ていて、それを読み込むようになっているから
それがないとダメってわけね
というか、これは本当は順序が逆
逆?
 DLL 関係なしに、 Exe 単独でデバッグする時も、この .pdb ファイルを
参照します
 BuildTest.exe をデバッグ実行する時には BuildTest.pdb が必要、って
こと?
そういうこと。その時も、 BuildTest.exe には BuildTest.pdb の
フルパスが書かれていてそれを参照してます
その時、実行する時に pdb ファイルがないと駄目ってことなんだ
 Exe はね。 DLL はなくてもいいんだけど、 Exe をデバッグ実行する時
には Exe に対応する .pdb ファイルが必要だから
…… DLL は、デバッグ実行できなくてもいい、ってこと?
ソースファイルを公開してない場合もあるから。 Win32API みたいに
あ、そうだった

/*
    Preview Next Story!
*/
こんな設定あるなんて知らなかったなー
というわけで、次回はプロジェクトの設定ダイアログについて
……なんか、すっごく難しい気がするんだけど
今回のとかも?
あ、デバッグのは分かりやすかったかも。あれ?
というわけで次回
< Version 15.20 プロジェクトの設定ダイアログ >
につづく!
ま、結構難しい部分かもしれないけどね
ええー!?
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。